C++中有的时候不可避免的必须返回一个对象,而不能返回一个reference或pointer

在之前的博客中有专门一章讲述在C++中为什么尽量在传参时用pass-by-reference取代pass-by-value,其主要目的是为了节省构造函数和析构函数的成本,但这不能完全的取代,假如有下面的一个类:

1 class Rational
2 {
3     public:
4         Rational(int numerator = 0, int denominator = 1);
5     private:
6         int n, d;
7 };

现在为此类添加成员函数operator*,不妨先找找以下的代码有什么问题:

const Rational& operator*(Rational& a, Rational& b)
{
    Rational result(a.n*b.n, a.d*b.d);
    return result;
}

这段代码有两个问题需要注意:第一 在函数内部定义了一个local对象,然后返回它的地址,而我们应该指导local对象会在退出函数时被销毁,所以如果用户使用这个reference指向的对象会出现”未定义错误“;第二 result的创建还是逃避不了构造函数调用的成本。

也许有人提出利用堆来取代栈存放这个对象,这样一来,对象就不会在函数调用结束时退出,即将代码改造如下:

const Rational& operator*(Rational& a, Rational& b)
{
    Rational *result = new Rational(a.n*b.n, a.d*b.d);
    return *result;
}

即使如此改造,依然改变不了需要调用构造函数的成本。此外,它无法对new出的那块内存进行释放,因为用户无法获取operator*返回的reference指向表示的对象背后指向它的指针。

或者还有人提出既然stack和heap存放对象分别会带来未定义和无法释放内存的问题,那就用local-static对象,这样一来就不需要构造函数的成本,函数返回的reference指向一个定义于函数内部的存放在静态区域的对象,程序结束前不会被销毁,也不需要释放内存,因而可以解决上面的几个问题,但是它存在多线程安全性的问题。另外,考虑下面的代码,看看是否有问题:

1  const Rational& operator*(const Rational& a, const Rational& b)
 2 {
 3     static Rational result;
 4     result.n = a.n*b.n;
 5     result.d = a.d*b.d;
 6 
 7     return result;
 8 }
 9 
10 
11 Rational a(2,1);
12 Rational b(2,3);
13 Rational c(3,4);
14 
15 if(a*b == c*a)
16 {
17     cout<<"equal"<<endl;
18 }

上面的代码的问题是15行的if语句总是真,所以17行的语句总会执行,原因是ab返回的reference指向的是一个static对象,当执行ca后,虽然这个static对象发生了变化,但ab返回的reference依旧指向这个static对象,也就是两次执行operator返回的reference其实一直指向同块区域中的对象,因而当然是相等的。

可以看到,试图返回一个reference参数在这里并不合适,这时就只好返回一个value对象,也因而必须付出调用构造函数和析构函数的成本,但这时保证程序运行结果正确是关键的,即代码修改如下:

1 friend const Rational operator*(const Rational& a, const Rational& b)
2 {
3     Rational result(a.n*b.n, a.d*b.d);
4     return result;
5 }

事实上,我在VS2010中运行下段代码时并没有出现预期中的”未定义错误“,我求助于一个C++群,结果有人指出编译器优化的可能性,也许真的是这个原因,只能说编译器能做的事越来越多,考虑的也越来越全。

1 const Rational& operator*(Rational& a, Rational& b)
 2 {
 3     Rational result(a.n*b.n, a.d*b.d);
 4     return result;
 5 }
 6 
 7 Rational a(2,1);
 8 Rational b(2,3);
 9 
10 const Rational c = a*b;    
11 const Rational d = c*b;

以上整理自Effective C++ 中文版第三版。

原文链接: https://www.cnblogs.com/sophia-yun/archive/2013/05/18/3086228.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/88990

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午11:54
下一篇 2023年2月9日 下午11:55

相关推荐