条款十五: 让operator=返回*this的引用
c++程序员经常犯的一个错误是让operator=返回void,这好象没什么不合理的,但它妨碍了连续(链式)赋值操作,所以不要这样做。
一般情况下几乎总要遵循operator=输入和返回的都是类对象的引用的原则,然而有时候需要重载operator=使它能够接受不同类型的参数。例如,标准string类型提供了两个不同版本的赋值运算符:
string& // 将一个string
operator=(const string& rhs); // 赋给一个string string& // 将一个char*
operator=(const char *rhs); // 赋给一个string
请注意,即使在重载时,返回类型也是类的对象的引用。
采用缺省形式定义的赋值运算符里,对象返回值有两个很明显的候选者:赋值语句左边的对象(被this指针指向的对象)和赋值语句右边的对象(参数表中被命名的对象)。哪一个是正确的呢?
例如,对string类(假设你想在这个类中写赋值运算符,参见条款11中的解释)来说有两种可能:
string& string::operator=(const string& rhs)
{
...
return *this; // 返回左边的对象
}
string& string::operator=(const string& rhs)
{
...
return rhs; // 返回右边的对象
}
首先,返回rhs的那个版本不会通过编译,因为rhs是一个const string的引用,而operator=要返回的是一个string的引用。
看起来这个问题很容易解决——只用象这样重新声明operator=:
string& string::operator=(string& rhs) { ... }
这次又轮到用到它的应用程序不能通过编译了!再看看最初那个连续赋值语句的后面部分:
x = "hello"; // 和x.op = ("hello"); 相同
因为赋值语句的右边参数不是正确的类型——它是一个字符串,不是一个string——编译器就要产生一个临时的string对象(通过stirng构造函数——参见条款m19)使得函数继续运行。就是说,编译器必须产生大致象下面这样的代码:
const string temp("hello"); // 产生临时string
x = temp; // 临时string传给operator=
编译器一般会产生这样的临时值(除非显式地定义了所需要的构造函数——见条款19),但注意临时值是一个const。这很重要,因为它可以防止传递到函数内的临时值被修改。
现在我们就可以知道如果string的operator=声明传递一个非const的stirng参数,应用程序就不能通过编译的原因了:对于没有声明相应参数为const的函数来说,传递一个const对象是非法的。这是一个关于const的很简单的规定。
所以,结论是,这种情况下你将别无选择:当定义自己的赋值运算符时,必须返回赋值运算符左边参数的引用,*this。如果不这样做,就会导致不能连续赋值,或导致调用时的隐式类型转换不能进行(字符串常量转为const string),或两种情况同时发生。
若返回rhs,则rhs必须是非const的,但是隐式类型转换要求rhs是const的。
最新文章
- Range Sum Query - Mutable
- C++ 回调函数的定义与用法
- MySQL数据库索引的设计原则
- PHPCMS联动菜单的调用函数get_linkage方法详解
- UVa 699 下落的树叶
- simplexml_load_string获取xml节点里的属性值
- 《搭建DNS内外网的解析服务》RHEL6
- android Button 切换背景,实现动态按钮和按钮颜色渐变
- 【编程范式】汇编解释swap方法
- [HDU] 2094 产生冠军(拓扑排序+map)
- PL/SQL Developer使用技巧、快捷键、存储过程调试
- PHP常用表达式用法
- 转:Spring历史版本变迁和如今的生态帝国
- Interpreting NotifyCollectionChangedEventArgs zz
- ORM学员管理系统
- 4.6 explain 之 rows
- fjwc2019 D2T2 定价 (栈+set+贪心)
- Android开发者选项 介绍
- WCF使用net.tcp绑定时的注意事项
- UVA - 1197 (简单并查集计数)
热门文章
- python学习一 hello world of python
- [Android]Android Design之Navigation Drawer
- linux 配置Java、Mysql、Tomcat、Redis开发环境
- POJ中和质数相关的三个例题(POJ 2262、POJ 2739、POJ 3006)
- 【转】MFC 自定义edit 限制输入十六进制内容 响应复制粘贴全选剪切的功能
- spring的设计思想
- SpringBoot Banner 图片定制修改
- 使用requests+BeaBeautiful Soup爬取妹子图图片
- 微信小程序 video组件 不随页面滚动
- 【转载】什么是Zero-Copy