读书笔记_Effective_C++_条款二十八:避免返回handlers指向对象内部成分
举个例子:
- class Student
- {
- private:
- int ID;
- string name;
- public:
- string& GetName()
- {
- return name;
- }
- };
这是一个学生的类,类里面有两个成员变量,一个是学生ID,用整数表示,另一个是姓名,用string表示。有一个公有的方法GetName(),获得学生的名字,根据条款20所说的,使用引用可以防止资源不必要地拷贝,那么在返回值这边就用string&。但现在问题来了,这个函数只是想返回学生的姓名,并不想用户对之进行修改,但返回引用却提供了这样的一个接口,如:
- int main()
- {
- Student s;
- s.GetName() = "Jerry";
- cout << s.GetName() << endl;
- }
就可以把名字进行修改。
你也许想到了,如果在前面加上const,像这样:
- const string& GetName()
- {
- return name;
- }
就可以阻止s.GetName() = “Jerry”这样的代码了。
但这样写还是存在问题,就是如果返回的引用生命周期比对象本身要长时,引用就会悬空,它会指向一个不存在的string。下面看一下“返回的引用生命周期比对象本身要长”的情况,这种情况还是很容易举出例子的,比如:
- const string& fun()
- {
- return Student().GetName();
- }
- int main()
- {
- string name = fun(); //name指向一个不存的对象的成员变量
- }
这时候即使name读取不报错,也是一个巨大的隐患,因为它已经是虚吊(dangling)的了。
这就是为什么函数如果“返回一个handle代表对象内部成分”总是危险的原因,不在于返回值是不是const,而是在于如果handle(指针或引用)传出去了,就会暴露在“handle比其所指对象更长寿”的风险下。
但有些情况还是需要返回handle的,比如string或者vector里面的operator[],就是返回的引用,因为需要对这里面的元素进行操作。
好了,总结一下:
避免返回handles(包括reference、指针、迭代器)指向对象内部,遵守这个条款可增加封装性,并将发生dangling handles的可能性降至最低。如果有必要必须要返回handles,在编写代码时就一定要注意对象和传出handle的生命周期。
读书笔记_Effective_C++_条款二十八:避免返回handlers指向对象内部成分的更多相关文章
- 读书笔记_Effective_C++_条款二十九:为“异常安全”而努力是值得的
还是举书上的例子: void PrettyMenu::changeBackground(std::istream& imgSrc) { lock(&mutex); delete bgI ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- 读书笔记_Effective_C++_条款二十六:尽可能延后变量定义式的出现时间
这个条款从字面意思还是很好理解的,就是在使用这个变量前才去定义,而不是很早就定义了它,而在很后面的时候才去使用.这个条款只适用于对变量声明位置没有要求的语言,比如C++.对于像C或者一些脚本语言,语法 ...
- 读书笔记_Effective_C++_条款二十五: 考虑写出一个不抛出异常的swap函数
在之前的理论上调用对象的operator=是这样做的 void swap(A& x) { std::swap(a, x.a); } A& operator=(const A& ...
- 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数
class A { private: int a; public: A(int x) :a(x){} A operator*(const A& x) { return A(a*x.a); } ...
- 读书笔记_Effective_C++_条款二十二:将成员变量声明为private
1.格式统一 在调用的时候,不会去想有没有(),一律是有get(),或者set()之类的. 2.封装 能直接访问得越少,表明封装性越高, 封装性越高,我们的顾虑就少了, 例如:我们a.data*0.9 ...
- 读书笔记_Effective_C++_条款三十八:通过复合塑模出has-a或者is-implemented-in-terms-of
如果说public是一种is-a的关系的话,那么复合就是has-a的关系.直观来说,复合就是在一个类中采用其他类的对象作为自身的成员变量,可以举个例子,像下面这样: class Person { pr ...
- 读书笔记_Effective_C++_条款三十:了解inline的里里外外
学过基本程序课的同学都知道,inline是内联的关键字,它可以建议编译器将函数的每一个调用都用函数本体替换.这是一种以空间换时间的做法.把每一次调用都用本体替换,无疑会使代码膨胀,但可以节省函数调用的 ...
- 读书笔记_Effective_C++_条款三十二:确定你的public继承继承塑模出is-a关系
这一条款是说的是公有继承的逻辑,如果使用继承,而且继承是公有继承的话,一定要确保子类是一种父类(is-a关系).这种逻辑可能与生活中的常理不相符,比如企鹅是生蛋的,所有企鹅是鸟类的一种,直观来看,我们 ...
随机推荐
- python之自然语言处理入门(一)
前言 NTLK是著名的Python自然语言处理工具包,记录一下学习NTLK的总结. 安装nltk pip install nltk # 测试 import nltk 安装相关的包 import nlt ...
- fullpage.js 具体使用方法
1.fullpage.js 下载地址 https://github.com/alvarotrigo/fullPage.js 2.fullPage.js 是一个基于 jQuery 的插件,它能够很方便 ...
- PyQt实现测试工具
测试工具: 1. 基本界面实现: # coding:utf-8 import sys import os import os.path import re import time from PyQt4 ...
- C/C++——[04] 语句
在 C/C++语言中,语句以“ :”结束.某些情况下,一组语句在一起共同完成某一特定的功能,可以将它们用大括号括起来.我们称之为语句组.语句组可以出现在任何单个语句出现的地方. 1. 分支语句 一般情 ...
- Python编程规范精简版
用四个空格缩进,不要用tab键:四个空格是在较小缩进(可以允许更大的嵌套深度)和较大缩进(可读性更好)之间的一个很好的折中.制表符会带来混乱,最好不要使用: 包装行保证每行不超过79个字符:这对那些使 ...
- caffe源码整个训练过程
Caffe源码 Blob protected: shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; ...
- HDU 4553 约会安排(线段树区间合并+双重标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 题目大意:就是有三种操作: ①DS x,安排一段长度为x的空闲时间跟屌丝一起,输出这段时间的起点 ...
- lr_save_searched_string函数的使用介绍
函数功能:在某一个字符缓冲区中搜索指定的字符串,并将搜到的字符串保存在参数中. 应用场合:可配合LoadRunner的关联功能,灵活获取服务器端返回的数据 举例:客服3.0工作流系统,工单处理每次都从 ...
- SaltStack的salt-ssh使用及LAMP状态设计部署(五)
一.salt-ssh的使用 官方文档:https://docs.saltstack.com/en/2016.11/topics/ssh/index.html (1)安装salt-ssh [root@l ...
- mysql左连接,右连接,内连接