[Effective C++ --021]必须返回对象时,别妄想返回其reference
引言
在条目20中,我们知道了值传递和引用传递的效率问题,因此在设计程序时,我们可能就尽可能来返回引用而不是值。
可是,可能会犯下面的一些错误:传递一些引用指向其实并不存在的对象。
第一节:返回临时变量的引用
假如我们有以下的例子,先看值传递
class A {
public:
A(int n = , int d = ):n(n),d(d) {}
private:
int n,d;
friend const A operator* (const A& l, const A& r);
};
在operator*系以值传递的方式返回了一个计算结果,联系到条款20,我们自然会想到,那么用引用传递试试。
因为函数返回的是A对象,所以函数创建新对象的方式有2:
1.在stack空间创建
const A& operator* (const A& l, const A& r) {
A result(l.n * r.n, l.d * r.d);
return result;
}
这样我们避免值传递的调用构造和析构函数,可是result是个临时变量,在函数推出前就被销毁了。任何对这个函数的调用都会是无意义的行为。
2.在heap空间创建
const A& operator* (const A& l, const A& r) {
A* result = new A(l.n * r.n, l.d * r.d);
return *result;
}
这样解决了上面临时变量的问题。可是,这个new出来的对象什么时候被释放呢?
就算我们调用A的时候很谨慎,但还是避免不了出错,比如
A w,x,y,z;
w = x * y * z; // 实际与operator*(operator*(x, y), z)相同
这里同一个语句例调用了两次operator*,因此两次使用new,也就需要两次delete,但却没有合理的办法让operator*使用者进行那些delete调用。这就会导致资源泄露。
经过上面两种方法都不行,可能你还会想到这种方法:我声明一个static对象不行么?
比如:
const A& operator* (const A& l, const A& r) {
static A result;
result = .....
return result;
}
看上去完美的解决了这个问题,那么我们这样使用的时候呢?
bool operator == (const A& l, const A& r);
A a,b,c,d;
if ((a*b) == (c*d)) {
....
}
结果就会出现:(a*b) == (c*d)总是为true,无论a,b,c,d是什么!
将(a*b) == (c*d)拆开来理解,我们就可以知道为什么了。
operator == (operator*(a, b), operator(c*d));
因为到最后位置,都会返回static对象的现值,也就不怪乎为什么返回true了。
◆总结
1.绝不要返回pointer或者referenc指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static对象。
[Effective C++ --021]必须返回对象时,别妄想返回其reference的更多相关文章
- EC笔记:第4部分:21、必须返回对象时,别返回引用
使用应用可以大幅减少构造函数与析构函数的调用次数,但是引用不可以滥用. 如下: struct St { int a; }; St &func(){ St t; return t; } 在返回t ...
- 条款21: 必须返回对象时,不要强行返回对象的reference
总结: 绝不要返回一个local栈对象的指针或引用:绝不要返回一个被分配的堆对象的引用:绝不要返回一个静态局部对象(为了它,有可能同时需要多个这样的对象的指针或引用). 条款4中给出了“在单线程环境中 ...
- 【21】必须返回对象时,别妄想返回器reference
1.考虑有理数Rational,有个友元操作符*,返回Rational对象.返回对象,导致临时对象的构造,析构.效率低,因此会想返回方法内局部对象的引用,这种方法不可行.为什么? 2.调用方法是在st ...
- Effective C++ -----条款21:必须返回对象时,别妄想返回其reference
绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个loc ...
- 必须返回对象时,别妄想返回其reference 【Effective C++ 条款21】
class Rational { public: Rational(, ) : n(numerator), d(denominator) { printf("Rational Constru ...
- 条款21:必须返回对象时,别妄想返回其reference(Don't try to return a reference when you must return an object)
NOTE: 1.绝不要返回pointer或reference 指向一个local stack 对象,或返回reference 指向一个heap-allocated对象,或返回pointer 或refe ...
- C++ 函数返回对象时并没有调用拷贝构造函数
#include <iostream> #include <vector> #include <string.h> using namespace std; cla ...
- Effective C++ -----条款12: 复制对象时勿忘其每一个成分
Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...
- 读书笔记_Effective_C++_条款二十一:当必须返回对象时,别妄想返回其reference
在栈空间的临时成员变量在函数生命期结束后无法传出 friend A& operator*(const A& a, const A& b) { A temp; temp.data ...
随机推荐
- C# 中的 ref 和 out 的意义和使用方法
原文C# 中的 ref 和 out 的意义和使用方法 向方法传递一个实参时,对应的形参会用实参的一个副本来初始化,不管形参是值类型(例如 int),可空类型(int?),还是引用类型,这一点都是成立的 ...
- 利用文件实现Free Pascal中的简单排序功能
此程序主要是验证文件功能的读写功能,总结到的东西有:①文件无论是读还是写,都要先建立链接关系才可以进行;②读与写不能同时进行,必须分开操作,这也可以理解,在实际鼠标操作时也是如此的!③读写后必须用cl ...
- 设计模式_C++源码+总结
C++源码下载: http://yunpan.cn/Q7fadjGgEJxib 提取码 63cb 总结:
- [九度OJ]1113.二叉树(求完全二叉树任意结点所在子树的结点数)
原题链接:http://ac.jobdu.com/problem.php?pid=1113 题目描述: 如上所示,由正整数1,2,3……组成了一颗特殊二叉树.我们已知这个二叉树的最后一个结点是n.现在 ...
- xhtml知识及head部分名词解
W3C: World Wide Web Con??? DTD: Document Type Defination DOCTYPE:Document Type meta:????? http-equiv ...
- C语言基础--宏
宏在C语言中经常使用,在linux的源码中可以看到很多宏的高级应用.因此不理解宏,就很难理解代码.本文参考一些互联网资料做一些总结,希望给大家带来帮助. 先说说使用宏的优点及缺点: 优点: 1.提高代 ...
- 查看本机IP地址及子网掩码(netmask)
通常有两种方式来查看本机IP地址及子网掩码,一种是在网路和共享中心中查看网路信息:一种是在cmd命令窗口查看. 下面分别介绍这两种方法: 1.在网路和共享中心中查看本机IP地址及子网掩码 (1)打开控 ...
- mysql fetch 系列函数
浏览器输出内容同上. 当使用 MYSQL_BOTH 或省略该参数是,将同时具有 MYSQL_NUM 与 MYSQL_ ASSOC 的特性. MySQL mysql_fetch_array 函数取得查询 ...
- 基于野火M3开发板(STM32F103VET6)的迷宫小球(重力感应控制)游戏开发
2013-03-03 这是研一上学期<实时嵌入式系统实验>课程的大作业,是利用野火板的资源,加上一个AHRS(Attitude and Heading Reference System,姿 ...
- Chrome 浏览器跨域和安全访问问题 使用 chrome的命令行标记:disable-web-security 参数联调线上数据
做前端的,用Ajax获取数据,是常有的事情,同域下自然没问题了,如果是不同域获取数据,浏览器就有个同源策略的限制. 如图: Origin * is not allowed by Access-Cont ...