如下为一个有理数类,其中包含一个用来计算乘积的函数:

 #include <iostream>

 using namespace std;

 class Rational
{
public:
Rational(int numerator = , int denominator = )
{
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(, ); // a = 1/2
Rational b(, ); // b = 3/5
Rational c = a * b; // c = 3/10 return ;
}

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

条款21:必须返回对象object时,不要返回其引用reference的更多相关文章

  1. mybatis返回boolean值时数据库返回null

    Servlet.service() for servlet [springDispatcherServlet] in context with path [/ms] threw exception [ ...

  2. (C/C++学习)21.C++中返回引用和返回对象以及传引用和传对象问题

    说明:在学习和编写C++代码时,经常会遇到这样的问题:一个带返回值的函数,到底应该返回值呢,还是应该返回引用呢:在传递参数的时候,是应该传递参数的引用呢,还是应该传值呢?请看下面代码: void my ...

  3. 13_Python的面向对象编程-类class,对象object,实例instance

    1.面向对象概述 1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组     2.对象是由类实例化出来的一个具体的对象         属性: 对象拥有的名词,用变量表示         ...

  4. JavaScript对象(Object)

         JavaScript的简单数据类型包括数字.字符串.布尔值.null值和undefined值,其他所有的值都是对象.数字.字符串.布尔值“貌似”对象,因为他们拥有方法,但是他们是不可变的. ...

  5. C++_类和动态内存分配4-有关返回对象的说明

    返回方式: 返回指向对象的引用: 指向对象的const引用: const对象:  =============================================== 返回指向const对象 ...

  6. 条款21: 必须返回对象时,不要强行返回对象的reference

    总结: 绝不要返回一个local栈对象的指针或引用:绝不要返回一个被分配的堆对象的引用:绝不要返回一个静态局部对象(为了它,有可能同时需要多个这样的对象的指针或引用). 条款4中给出了“在单线程环境中 ...

  7. 【21】必须返回对象时,别妄想返回器reference

    1.考虑有理数Rational,有个友元操作符*,返回Rational对象.返回对象,导致临时对象的构造,析构.效率低,因此会想返回方法内局部对象的引用,这种方法不可行.为什么? 2.调用方法是在st ...

  8. 条款21:必须返回对象的时候,不要妄想使其返回reference

    //先看看下面这个例子 class Rational{ public: Rational(int num, int denu) :numirator(num), denumirator(denu); ...

  9. [Effective C++ --021]必须返回对象时,别妄想返回其reference

    引言 在条目20中,我们知道了值传递和引用传递的效率问题,因此在设计程序时,我们可能就尽可能来返回引用而不是值. 可是,可能会犯下面的一些错误:传递一些引用指向其实并不存在的对象. 第一节:返回临时变 ...

随机推荐

  1. 浅谈 cookie 和 session

    1.关闭浏览器后,session是否还存在? session在服务器和客户端各保留一个副本,关闭浏览器与否和session是否存在没有任何关系. session采取的是服务器端保持状态的方案,它存储在 ...

  2. max subquence sum(n^2)

    #include<cstdio>#include<cstring>const int maxn=100005;int buf[maxn];int main(){ freopen ...

  3. 在XML序列化时去除默认命名空间xmlns:xsd和xmlns:xsi

    摘 自: http://blog.csdn.net/fxhflower/article/details/7276820 可使用以下代码: //Create our own namespaces for ...

  4. 前端开发之-------------合理利用CSS的权重----------------

    什么是CSS的权重?对于前端工程师来说,这是一个很基础的问题,如果前端工程师没有深刻理解这个概念,则很难写出高质量的CSS代码. 那么到底什么是CSS的权重呢?我们又怎么来进行判定CSS的权重呢? 讨 ...

  5. Centos6.5系统初学者基本系统配置1

    作为一个初步接触linux-Centos的菜鸟来说,Centos在基本软件安装是一件比较令人头疼的事情,下面我将我初步使用linux的一些问题进行了汇总和记录,希望对大家有所帮助,这些东西也是在网友的 ...

  6. 安装 centos7 注意事项

    最近一直没有写博客,把之前的折腾记录写下. 1 下载好镜像文件,刻录光盘. 2  用DVD安装CENTOS7 3 有些处理器不支持Cento7安装,需要重新编译内核文件.我不懂 . 我用的ACER  ...

  7. ie使用firebug

    在网页插入以下代码即可. <script type="text/javascript" src="http://getfirebug.com/releases/li ...

  8. Web 应用程序项目 MvcApplication1 已配置为使用 IIS。

    今天网上下了一个项目,加载不了,并报如下错误: Web 应用程序项目 MvcApplication1 已配置为使用 IIS. 若要访问本地 IIS 网站,必须在管理员帐户的上下文中运行 Visual ...

  9. android自定义控件实现TextView按下后字体颜色改变

    今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能 直接看图片             第一张是按下后截的图,功能很简单, ...

  10. WindowManager和WindowManager.LayoutParams的使用以及实现悬浮窗口的方法

    写Android程序的时候一般用WindowManager就是去获得屏幕的宽和高,来布局一些小的东西.基本上没有怎么看他的其他的接口. 这两天想写一个简单的类似于Toast的东西,自定义布局,突然发现 ...