Effective C++ 详解条款21:必须返回对象时,别返回其reference
如果在stack
空间创建一个local
变量,并且你函数返回一个reference
指向该local
对象,将导致”无定义行为“,同样在,heap
上也会导致operator*
使用者不能获取到reference
背后的指针而资源泄漏。
//考虑一个用以表现有理数(rational numbers)的 class,内含一个函数用来计算两个有理数的乘积:
class Rational {
public:
Rational (int numerator = 0,int denominator 1) ; //条款24说明为什么这个构造函数不声明为explicit
...
private:
int n, d; //分子(numerator)和分母(denominator)
friend
const Rational operator*(const Rational& lhs, const Rational& rhs) ; //条款3说明为什么返回类型是const
};
//第一种情况 在stack空间创建新对象,定义一个local变量,就是在stack空间创建对象。
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
Rational result (lhs.n * rhs.n,lhs.d * rhs.d); //警告!糟糕的代码!
return result;
}
//第二种情况 在heap内构造一个对象,并返回reference指向它。Heap-based对象由new创建,所以得写一个heap-based operator*
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
Rational* result = new Rational(lhs.n * rhs.n,lhs.d * rhs.d); //警告!糟糕的代码!
return *result;
}
第一种情况:可以拒绝这种做法,因为目标是要避免调用构造函数,而result
却必须像任何对象一样地由构造函数构造起来。更严重的是:这个函数返回一个reference
指向result
,但result
是个local
对象,而local
对象在函数退出前被销毁了。因此,这个版本的operator*
并未返回reference
指向某个Rational
,它返回的reference
指向一个“从前的”Rational
;一个旧时的Rational
;-一个曾经被当做Rational
但如今已经成空、发臭、败坏的残骸,因为它已经被销毁了。任何调用者甚至只是对此函数的返回值做任何一点点运用,都将立刻坠入“无定义行为”的恶地。
任何函数如果返回一个reference
指向某个local
对象,都是行不通的。同样,如果函数返回指针指向一个local
对象,也是如此。
第二种情况:函数需要付出“构造函数调用”的代价,因为分配所得的内存将以一个适当的构造函数完全初始化动作。
不论是在stack空间内,还是heap空间,都因为对operator*
返回的结果调用构造函数而受惩罚。
**一个“必须返回新对象”的函数的正确写法是:**就让那个函数返回一个新对象。对Rational
的 operator*
而言意味以下写法(或其他本质上等价的代码):
inline const Rational operator * (const Rational& lhs, const Rational& rhs)
{
return Rational (lhs.n * rhs.n, lhs.d * rhs.d);
}
总结:
绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static对象而有可能需要多个这样的对象。
推荐阅读
-
条款21:必须返回对象时,别勉强返回其reference
-
Effective C++条款21:必须返回对象时,别妄想返回其reference
-
条款21(二):必须返回对象时,别妄想返回其reference
-
条款21(一):必须返回对象时,别妄想返回其reference
-
条款21:必须返回对象时,别妄想返回其reference——120
-
Effective C++条款21:必须返回对象时,别妄想返回其引用
-
条款21:必须返回对象时,别妄想返回其reference
-
读书笔记《Effective C++》条款21:必须返回对象时,别妄想返回其reference
-
Effective C++ 详解条款21:必须返回对象时,别返回其reference
-
读书笔记《Effective c++》 条款21 必须返回对象时,别妄想返回其reference