重载赋值运算符中需要注意的两个问题

前言

  如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符。

  然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符。

第一点:请返回 reference to *this

  我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用。

  因此,在重载运算符函数末尾请写上如这样的语句 return *this;

  除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做。

第二点:处理好自我赋值

  首先,我们看一段问题代码:

 1 // 位图资源类
 2 class Bitmap { /*......*/ };
 3
 4 // 位图资源管理类
 5 class Widget {
 6 public:
 7     //......
 8     Widget & operator=(const Widget & rhs);
 9     //......
10 private:
11     //......
12     Bitmap *pb;    // 位图资源。指针类型,指向 heap 分配而得的空间
13     //......
14 };
15
16 Widget & Widget::operator=(const Widget & rhs)
17 {
18     delete pb;    // 删除原有资源
19     pb = new Bitmap(*rhs.pb);    // 申请新的资源并存放右操作数的数据
20     return *this;
21 }

  问题出在重载函数中,如果左右操作数是相同的对象,delete 掉原有资源之后,所有数据信息就全丢了。

  因此,运算符重载函数需要加上一个证同测试:

 1 Widget & Widget::operator=(const Widget & rhs)
 2 {
 3     // 加入证同测试
 4     if (this == &rhs)
 5         return *this;
 6
 7     delete pb;    // 删除原有资源
 8     pb = new Bitmap(*rhs.pb);    // 申请新的资源
 9
10     return *this;
11 }

  但这依然不是最好的做法:因为 new 有可能失败,导致资源丢失。

  下面这个精心设计的重载函数才是我们需要的:

1 Widget & Widget::operator=(const Widget & rhs)
2 {
3     Bitmap * pOrig = pb;
4     pb = new Bitmap(*rhs.pb);
5     delete pOrig;
6
7     return *this;
8 }

  这个实现就保证了赋值的安全,健壮,是个非常可取的方案。

小结

  赋值运算符还有一些其他的非常可取的实现,这里就不一一讲解了。

时间: 2024-08-04 16:17:26

重载赋值运算符中需要注意的两个问题的相关文章

第九章:重载赋值运算符中需要注意的两个问题

前言 如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符. 然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符. 第一点:请返回 reference to *this 我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用. 因此,在重载运算符函数末尾请写上如这样的语句 return *this; 除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做. 第二点:处理好

拷贝构造函数(三)——重载赋值运算符

拷贝构造函数(一)--哲学三连:http://www.cnblogs.com/tenjl-exv/p/8017814.html 拷贝构造函数(二)--深拷贝与浅拷贝:http://www.cnblogs.com/tenjl-exv/p/8017909.html 拷贝构造函数(三)--重载赋值运算符:http://www.cnblogs.com/tenjl-exv/p/8017983.html 关于拷贝函数中的赋值操作符重载  以下讨论中将用到的例子: 1 class CExample 2 { 3

重载赋值运算符 && 对象

class CMessage { private: char * m_pMessage; public: void showIt()const { cout << m_pMessage << endl; } //构造函数 CMessage(const char* text="Default message") { cout << "Constructor difinition" << endl; size_t leng

C++进阶--处理拷贝赋值运算符中自赋值的情况

//############################################################################ /* * 处理拷贝赋值运算符=中自赋值的情况 * * * 运算符重载: 利用人们的直觉,减少学习曲线 */ // 自赋值的情况 dog dd; dd = dd; // 看起来很傻 dogs[i] = dogs[j]; // 看起来不怎么傻 /* 实现赋值运算符 */ class collar; class dog { collar* pCo

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 选择调用的进程为 24 i386 getuid sys_getuid1647 i386 getgid sys_getgid16 使用库函数API方式 使用C代码中嵌入汇编代码方式

Linux中生成密钥的两种方法

Linux中生成密钥的两种方法 SSH服务支持一种安全认证机制,即密钥认证.所谓的密钥认证,实际上是使用一对加密字符串,一个称为公钥(publickey), 任何人都可以看到其内容,用于加密:另一个称为密钥(privatekey),只有拥有者才能看到,用于解密.通过公钥加密过的密文使用密钥可以轻松解密,但根据公钥来猜测密钥却十分困难. ssh的密钥认证就是使用了这一特性.服务器和客户端都各自拥有自己的公钥和密钥.如何使用密钥认证登录linux服务器呢? 在使用密钥认证远程登入linux之前,我们

实验--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用(杨光)

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 攥写人:杨光  学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验要求: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/sys

Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完成测试代码)

MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明文是yanzi1225627,得到MD5加密后的字符串是:14F2AE15259E2C276A095E7394DA0CA9  但不能由后面一大串倒推出yanzi1225627.因此可以用来存储用户输入的密码在服务器上.现在下载文件校验文件是否中途被篡改也是用的它,原理参见:http://blog.c

WORD中如何让前两页不显示页码

WORD中如何让前两页不显示页码   上稿人:ojn 点击率: 15191   我们有时在用word编辑文档时,会遇上第一.二页无需显示页码,第三页才是正文的第一页时,该如何正确插入页码呢? 以word 2010为例,方法如下: 假如第1-2页无页码,第3页开始插入页码,起始页为1. 1.将光标定位在第2页末尾处,点击“页面布局——(页面设置)分隔符——(分节符)下一页” 2.双击第3页的页脚处,进入页眉和页脚的编辑状态,点击工具栏中的“链接到前一条页眉”按钮,使其使其退出高亮状态. 3.点击“