条款21:必须返回对象object时,不要返回其引用reference
如下为一个有理数类,其中包含一个用来计算乘积的函数:
#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的更多相关文章
- mybatis返回boolean值时数据库返回null
Servlet.service() for servlet [springDispatcherServlet] in context with path [/ms] threw exception [ ...
- (C/C++学习)21.C++中返回引用和返回对象以及传引用和传对象问题
说明:在学习和编写C++代码时,经常会遇到这样的问题:一个带返回值的函数,到底应该返回值呢,还是应该返回引用呢:在传递参数的时候,是应该传递参数的引用呢,还是应该传值呢?请看下面代码: void my ...
- 13_Python的面向对象编程-类class,对象object,实例instance
1.面向对象概述 1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组 2.对象是由类实例化出来的一个具体的对象 属性: 对象拥有的名词,用变量表示 ...
- JavaScript对象(Object)
JavaScript的简单数据类型包括数字.字符串.布尔值.null值和undefined值,其他所有的值都是对象.数字.字符串.布尔值“貌似”对象,因为他们拥有方法,但是他们是不可变的. ...
- C++_类和动态内存分配4-有关返回对象的说明
返回方式: 返回指向对象的引用: 指向对象的const引用: const对象: =============================================== 返回指向const对象 ...
- 条款21: 必须返回对象时,不要强行返回对象的reference
总结: 绝不要返回一个local栈对象的指针或引用:绝不要返回一个被分配的堆对象的引用:绝不要返回一个静态局部对象(为了它,有可能同时需要多个这样的对象的指针或引用). 条款4中给出了“在单线程环境中 ...
- 【21】必须返回对象时,别妄想返回器reference
1.考虑有理数Rational,有个友元操作符*,返回Rational对象.返回对象,导致临时对象的构造,析构.效率低,因此会想返回方法内局部对象的引用,这种方法不可行.为什么? 2.调用方法是在st ...
- 条款21:必须返回对象的时候,不要妄想使其返回reference
//先看看下面这个例子 class Rational{ public: Rational(int num, int denu) :numirator(num), denumirator(denu); ...
- [Effective C++ --021]必须返回对象时,别妄想返回其reference
引言 在条目20中,我们知道了值传递和引用传递的效率问题,因此在设计程序时,我们可能就尽可能来返回引用而不是值. 可是,可能会犯下面的一些错误:传递一些引用指向其实并不存在的对象. 第一节:返回临时变 ...
随机推荐
- oracle 将查询到的数据插入表
1. 新增一个表,通过另一个表的结构和数据 create table tab1 as select * from tab2 2. 如果表存在: insert into tab1 select * fr ...
- 使用FFmpeg解码H264-2016.01.14
使用jni方式调用FFmepg项目中接口,对H264裸码进行解码. 该Demo主要实现从文件中读取H264编码的视频流,然后使用FFmpeg解码,将解码后的码流保存到文件. 工程目录结构如图所示: A ...
- JavaScript 性能优化1
一直在学习javascript,也有看过<犀利开发Jquery内核详解与实践>,对这本书的评价只有两个字犀利,可能是对javascript理解的还不够透彻异或是自己太笨,更多的是自己不擅于 ...
- 【MVC】ASP.NET MVC HtmlHelper用法大全
1.ActionLink <%=Html.ActionLink("这是一个连接", "Index", "Home")%> 带 ...
- LINQ to XML 实战
LINQ to XML 轴定义:创建XML树或将XML文档加载到XML树之后,可以进行查询,从而查找元素并检索它们的值. 两类轴方法:-一些轴就是XELement和XDocument类中返回IEnum ...
- Loadrunner:安装LR11时提示缺少vc2005_sp1_with_atl_fix_redist
[问题现象] 安装LR11时提示缺少vc2005_sp1_with_atl_fix_redist: [解决办法] 手动安装缺少的组件,LR安装包中已自带该组件,为何不自动捕捉异常去获取该自带的组件去安 ...
- 017Makefile工程管理
1.为什么需要Makefile? 利用Makefile和make的合作,可以把很多很多的工作合并成一个非常简单的命令:make: make能够使整个程序的编译.链接只需要一个命令(make)就可以完成 ...
- Ubuntu 14.04下java开发环境的搭建--1--JDK的安装
说明:以下内容均是本人个人经验,接触ubuntu系统是从10.04开始,转眼转眼之间已经四年了,经常浏览各种相关论坛,发现从我刚开始基础到现在,论坛上还有很多人在问关于JAVA环境配置的相关问题.所以 ...
- vim 文字插入
我们知道VIM中,普通的复制和粘贴都是YY和PP.那么怎么将vim以外的文件插入到vim编辑器中呢!这是个问题: 首先我们要选中想要插入的文字,如: 然后进入vim插入模式:SHIFT + Inser ...
- Jquery 利用单个复选款(checkbox)实现全选、反选
1 <script type="text/javascript"> $(function(){ //全选 $("#CheckedAll").clic ...