首页 > 代码库 > 条款21:必须返回对象时,别妄想返回其reference
条款21:必须返回对象时,别妄想返回其reference
条款21:必须返回对象时,别妄想返回其reference
引用只是对象的一种别名当使用引用的时候,请确认他的另一个身份在哪?
class Rational { public: Rational(int x, int y) : m_x(x), m_y(y){} //返回const是属于类型保护,friend修饰,以后条款详说 friend const Rational operator + (const Rational &lhs, const Rational &rhs) { Rational temp(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //还有更好的做法 return temp; } private: int m_x; int m_y; };实现+号重载,我们采用return value,根据前面条款,返回value会调用一系列拷贝构造函数,析构函数的成本,于是我们修改为return reference
friend const Rational& operator + (const Rational &lhs, const Rational &rhs) { Rational temp(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //还有更好的做法 return temp; }
+号返回的引用对象在哪?我们看到在函数中创建一个临时对象temp,这个是属于栈空间对象,跳出函数作用域被回收,则引用的对象已经不存在了,程序会出现不可意料的行为。
上面我们提到函数实现还有一个更好的做法
friend const Rational operator + (const Rational &lhs, const Rational &rhs) { return Rational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //标准做法 }分析下:第一种做法是创建临时对象,调用构造函数初始化,返回时调用拷贝构造函数初始化存放返回值的外部变量,最后调用析构函数。而第二种是编译器直接创建临时对象并初始化外部变量,省去调用拷贝构造函数和析构函数。
如果考虑到在heap里面创建对象不会容易被回收,并使用reference返回,那么这个代价更大。
friend const Rational& operator + (const Rational &lhs, const Rational &rhs) { return *(new Rational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y)); }看下面调用
Rational x(1,2), y(3, 4), z(5, 6); Rational r = x + y + z;调用了两次operator +,两次new调用分配内存,但没有合理的方法delete内存,因为没有合理的方法取得返回reference的那个指针,导致内存泄露。
如果还是希望让函数返回reference而通过定义一个local-static对象替代heap对象,那么这个代价不比heap方法的小。
friend const Rational& operator + (const Rational &lhs, const Rational &rhs) { static Rational sRational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); return sRational; }
使用了静态变量在多线程安全性中存在隐患这一个问题暂且不说,还有一个是调用判断相等时出现逻辑错误
调用==判断Rational x(1,2), y(3, 4), z(5, 6), w(7, 8); if ((x + y) == (z + w)) { cout<<"equal\n"; }因为+号返回引用,而引用执行的对象时static,两次的+号返回reference其实是指向同一个对象,那==值判断永远相等。
记住
绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static对象而有可能同时需要多个这样的对象.条款4已经为"在单线程环境中合理返回reference指向一个local static对象"提供一份设计实例.
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。