引言

在条目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的更多相关文章

  1. EC笔记:第4部分:21、必须返回对象时,别返回引用

    使用应用可以大幅减少构造函数与析构函数的调用次数,但是引用不可以滥用. 如下: struct St { int a; }; St &func(){ St t; return t; } 在返回t ...

  2. 条款21: 必须返回对象时,不要强行返回对象的reference

    总结: 绝不要返回一个local栈对象的指针或引用:绝不要返回一个被分配的堆对象的引用:绝不要返回一个静态局部对象(为了它,有可能同时需要多个这样的对象的指针或引用). 条款4中给出了“在单线程环境中 ...

  3. 【21】必须返回对象时,别妄想返回器reference

    1.考虑有理数Rational,有个友元操作符*,返回Rational对象.返回对象,导致临时对象的构造,析构.效率低,因此会想返回方法内局部对象的引用,这种方法不可行.为什么? 2.调用方法是在st ...

  4. Effective C++ -----条款21:必须返回对象时,别妄想返回其reference

    绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个loc ...

  5. 必须返回对象时,别妄想返回其reference 【Effective C++ 条款21】

    class Rational { public: Rational(, ) : n(numerator), d(denominator) { printf("Rational Constru ...

  6. 条款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 ...

  7. C++ 函数返回对象时并没有调用拷贝构造函数

    #include <iostream> #include <vector> #include <string.h> using namespace std; cla ...

  8. Effective C++ -----条款12: 复制对象时勿忘其每一个成分

    Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...

  9. 读书笔记_Effective_C++_条款二十一:当必须返回对象时,别妄想返回其reference

    在栈空间的临时成员变量在函数生命期结束后无法传出 friend A& operator*(const A& a, const A& b) { A temp; temp.data ...

随机推荐

  1. Cookie设置HttpOnly,Secure,Expire属性

    在eclipese中创建Web工程时,有个dynamic web module version选项,首先解释下这个选项的意思: http://stackoverflow.com/questions/3 ...

  2. PHP错误:Forbidden You don't have permission to access / on this server.

    今天在测试一个php程序的时候,发现这个问题: Forbidden You don't have permission to access / on this server. 开始的时候我是用http ...

  3. oracle 有关大数据

    一. oracle大数据量分区后查询效率低下的一些建议: 1 对于当前表tm_bus_realtime_log.查看它的索引,只有一个(索引名:INDEX_BUS_REALTIME 字段名:UPLOA ...

  4. [转] C# Winform 拦截关闭按钮触发的事件

    原文 C# Winform 拦截关闭按钮触发的事件 用户关闭软件时,软件一般会给“是否确认关闭”的提示. 通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭:否则把FormClos ...

  5. java jvm学习笔记九(策略文件)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao/article/details/8271407 课程源码:http://download.csdn.net/detail ...

  6. POJ 3126 Prime Path BFS搜索

    题意:就是找最短的四位数素数路径 分析:然后BFS随便搜一下,复杂度最多是所有的四位素数的个数 #include<cstdio> #include<algorithm> #in ...

  7. bzoj 3110 [Zjoi2013]K大数查询(树套树)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置 ...

  8. MVC5中使用KinEditor

    参考:http://www.cnblogs.com/weicong/archive/2012/03/31/2427608.html 第一步 将 KindEditor 的源文件添加到项目中,建议放到 / ...

  9. 【noip2012】疫情控制

    题意: 给出一颗n个节点有边权的树 和m个军队所在的位置 军队从某节点移动到相邻节点要花费边长度的时间 求最少要多少时间使得根节点(编号为1)到每个叶子的路径上最少有一支军队(根节点不能有军队) 题解 ...

  10. HDU4862-Jump(最大流量最大费用流)

    题意:有n*m的格子,每一个格子包含一个数字,0-9.你初始的能量为0,你可以玩k次,每一个你可以选择你现在的格子的正下方或者正右方的任意一个格子跳,但必须是之前没有跳过的格子.每玩一次你都可以跳任意 ...