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的。

最新文章

  1. Range Sum Query - Mutable
  2. C++ 回调函数的定义与用法
  3. MySQL数据库索引的设计原则
  4. PHPCMS联动菜单的调用函数get_linkage方法详解
  5. UVa 699 下落的树叶
  6. simplexml_load_string获取xml节点里的属性值
  7. 《搭建DNS内外网的解析服务》RHEL6
  8. android Button 切换背景,实现动态按钮和按钮颜色渐变
  9. 【编程范式】汇编解释swap方法
  10. [HDU] 2094 产生冠军(拓扑排序+map)
  11. PL/SQL Developer使用技巧、快捷键、存储过程调试
  12. PHP常用表达式用法
  13. 转:Spring历史版本变迁和如今的生态帝国
  14. Interpreting NotifyCollectionChangedEventArgs zz
  15. ORM学员管理系统
  16. 4.6 explain 之 rows
  17. fjwc2019 D2T2 定价 (栈+set+贪心)
  18. Android开发者选项 介绍
  19. WCF使用net.tcp绑定时的注意事项
  20. UVA - 1197 (简单并查集计数)

热门文章

  1. python学习一 hello world of python
  2. [Android]Android Design之Navigation Drawer
  3. linux 配置Java、Mysql、Tomcat、Redis开发环境
  4. POJ中和质数相关的三个例题(POJ 2262、POJ 2739、POJ 3006)
  5. 【转】MFC 自定义edit 限制输入十六进制内容 响应复制粘贴全选剪切的功能
  6. spring的设计思想
  7. SpringBoot Banner 图片定制修改
  8. 使用requests+BeaBeautiful Soup爬取妹子图图片
  9. 微信小程序 video组件 不随页面滚动
  10. 【转载】什么是Zero-Copy