- 如果返回的对象为reference有什么问题
- 有这样的有理数相乘的例子
class Rational { public: Rational(int numerator = 0, int denominator = 1); private: int n, d; //分子和分母 // 返回对象为reference friend const Rational& operator*(const Rational& lhs, const Rational& rhs); };
那么operator*内的函数需要在heap或stack上新建Rational对象来返回。
- 在heap上新建
friend const Rational& operator*(const Rational& lhs, const Rational& rhs) { Rational result(lhs.n*rhs.n, lhs.d*rhs.d); return result; //局部变量result在退出函数已经被销毁,这是最常见的错误写法 }
- 在stack上新建
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出来的对象,由于是refence类型,故不会有额外的构造,析构函数的开销,但是谁,在哪里去delete呢?就算可以不忘记delete,但也无法保证不会有内存泄漏的操作。比如下面这样
Rational w, x, y, z; w = x*y*z; //相当于operator*(operator*(x,y),z);
operator*(x,y)执行了一次new 操作, operator*(operator*(x,y),z);也执行了new操作,但现在只有w对象是可以拿到的,那么只能delete由operator*(operator*(x,y),z); new出来的对象,那operator*(x,y) new出来的对象就没有被delete,这不就内存泄露了嘛
- 返回static 对象
friend const Rational& operator*(const Rational& lhs, const Rational& rhs) { static Rational result; //result=...; return *result; //返回static对象 }
第一个问题就是:多线程不安全,其次就是下面这种写法永远为真
//判断两个对象相等否 bool operator==(const Rational& lhs,const Rational& rhs); int main() { Rational a,b,c,d; if((a*b)==(c*d)){ //永远为真 等价于if( operator==(operator*(a,b), operator*(c,d)) ) } else{ } }
比如先调用operator*(a,b),那么会有一个static Rational result;再调用operator*(c,d),那么由于局部static的特性:不会再产生新的static Rational result;用的是之前operator*(a,b)的那个static对象,所以if((a*b)==(c*d))永远为真。。。
总之: 返回的对象为reference会带来很多问题,直接不要返回reference就可以了