条款21:必须返回对象object时,不要返回其引用reference
2015-05-29 10:58
656 查看
如下为一个有理数类,其中包含一个用来计算乘积的函数:
1> 如果上述函数operator*返回一个Rational&会怎么样呢?编译器会发出警告说返回一个local变量的引用。我们知道这个变量是在stack上存放的,在函数退出时就被销毁了,因此是返回了一个指向销毁空间的引用,如果调用这用这个返回的引用来工作,极有可能发生“行为没有定义”的结果。因此切记不要返回一个指向local变量的引用。
2 > 但是我们现在又会想,我可以在heap上创建这个对象啊,这样返回引用就不是指向临时对象了,如下所示:
这样做确实可以避免返回临时对象的引用,但是还是存在问题:new出来的对象谁来负责delete啊?,如下使用时:
Rational w, x, y, z;
w = x * y * z;
相当于调用operator*(operator*(x, y), z),即new了两次,那么就需要delete两次,但是使用者却没办法得到reference背后的指针,因此发生内存泄漏了。
3> 当然了或许你还知道一种避免调用构造函数的解决办法,那就是使用local static特性:
如果执行如下调用:
if((a * b) == (c * d)),会发现 if 条件永远为真,不论如何选择abcd,这是什么原因?这就是static的特性了,在等号两边比较的数都由static变量指定,虽然计算a * b和c * d时,result都会改变,但是不论哪个乘积先被计算,最终只有一份static变量,就是说最后比较时,等价于要么是:a * b == a * b,要么是c * d == c * d。
因此结论是:
无论是stack还是heap,如果应该返回object时,最好不要返回reference。
绝不要返回指向local stack对象的reference或者pointer。
绝不要返回指向local static对象reference或者pointer。
绝不要返回指向heap object的reference。
#include <iostream> using namespace std; class Rational { public: Rational(int numerator = 0, int denominator = 1) { n = numerator; d = denominator; } private: int n, d; friend const Rational operator*( const Rational& lhs, const Rational& rhs) { Rational result(lhs.n * rhs.n, lhs.d * rhs.d); return result; } }; int main() { Rational a(1, 2); // a = 1/2 Rational b(3, 5); // b = 3/5 Rational c = a * b; // c = 3/10 return 0; }
1> 如果上述函数operator*返回一个Rational&会怎么样呢?编译器会发出警告说返回一个local变量的引用。我们知道这个变量是在stack上存放的,在函数退出时就被销毁了,因此是返回了一个指向销毁空间的引用,如果调用这用这个返回的引用来工作,极有可能发生“行为没有定义”的结果。因此切记不要返回一个指向local变量的引用。
2 > 但是我们现在又会想,我可以在heap上创建这个对象啊,这样返回引用就不是指向临时对象了,如下所示:
friend const Rational& operator*( const Rational& lhs, const Rational& rhs) { Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d); return *result; }
这样做确实可以避免返回临时对象的引用,但是还是存在问题:new出来的对象谁来负责delete啊?,如下使用时:
Rational w, x, y, z;
w = x * y * z;
相当于调用operator*(operator*(x, y), z),即new了两次,那么就需要delete两次,但是使用者却没办法得到reference背后的指针,因此发生内存泄漏了。
3> 当然了或许你还知道一种避免调用构造函数的解决办法,那就是使用local static特性:
const Rational& operator(const Rational& lhs, const Rational& rhs) { static Rational result; // static对象,此函数返回该对象的reference result = ...; return result; }
如果执行如下调用:
if((a * b) == (c * d)),会发现 if 条件永远为真,不论如何选择abcd,这是什么原因?这就是static的特性了,在等号两边比较的数都由static变量指定,虽然计算a * b和c * d时,result都会改变,但是不论哪个乘积先被计算,最终只有一份static变量,就是说最后比较时,等价于要么是:a * b == a * b,要么是c * d == c * d。
因此结论是:
无论是stack还是heap,如果应该返回object时,最好不要返回reference。
绝不要返回指向local stack对象的reference或者pointer。
绝不要返回指向local static对象reference或者pointer。
绝不要返回指向heap object的reference。
相关文章推荐
- Cocoa 框架 For iOS(一) 框架的介绍,Objectivie-C运行时能力的解析等
- BING : Binarized Normed Gradients for Objectness Estimation at 300fps 论文笔记
- Windows之SignalObjectAndWait
- Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
- Chapter12. Foundation Classes and selector in Objective-C
- oc中谓词的使用(NSPredicate)
- 调用nil对象的方法(Calling Methods on Nil)
- oc中数组的四种遍历方式及比较
- IOS开发学习27 ObjectC 自带json解析方法的使用
- Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved tran
- 泛型限定<? extends Object>
- Getting SharePoint objects (spweb, splist, splistitem) from url string
- insufficient permission for adding an object to repository database ./objects
- Objective-C 类继承关系
- 继承自NSObject的类不能用CGRect
- ObjectC 类的一些问题解析
- Objective_C学习日记(1)--OC中类和实例的基本使用
- Python Dict -> Object
- c字符串与NSString之间的转换
- Objective-C语言的一些基础特性