【C++永不过时的语言】=运算符重载应注意点
发布日期:2021-06-29 14:30:10 浏览次数:3 分类:技术文章

本文共 1456 字,大约阅读时间需要 4 分钟。

文章目录

1.默认=运算符重载函数的局限

我们知道,当我们定义一个类A的时候,即使类体中我们什么都不写,C++编译器也将自动为A 产生下面四个缺省函数

A(void); // 缺省的无参数构造函数A(const A &a); // 缺省的拷贝构造函数~A(void); // 缺省的析构函数A & operate =(const A &a); // 缺省的赋值=函数

本文主要讲=运算符的重载,因此暂且不去管其它三个函数,重心放在赋值运算符重载函数上。刚接触C++的同学可能会疑惑:既然编译器能自动生成=运算符重载函数了,为什么还要我们自己再去写了。

但是对于含有指针的类,编译器自动生成的=重载函数就满足不了我们的需求了,

class String{
public: private: char *data; // 用于保存字符串};

上面的String类没有自定义=运算符重载函数,当我们在程序中对String对象进行赋值操作时。

String a("Hello");String b("World");b = a; //赋值操作

使用的是编译器自动生成的=重载函数,该函数作用是将数据成员按bit拷贝,最后的结果是导致最后a和b指向同一块字符串"Hello",而b原来指向的字符串"World"现在没有主人。这样会导致以下几个问题。

(1)  b原来指向的字符串"World"成了无主之魂,没有机会释放,造成内存泄露。(2)  a,b现在指向同一字符串"Hello",可能会被释放2次,也会造成错误。(3)  a,b现在指向同一字符串"Hello",通过a修改字符串会影响b,反之亦然,会导致不确定的行为产生。

在这里插入图片描述

2.防止自我拷贝

不少同学可能知道大部分情况编译器自动生成的=重载函数不够用,需要自己编写,于是毫不犹豫的写出了下面的=重载函数。

String& String::operator=(const String &rhs){
delete[] data; data = new char[strlen(rhs.data)+1]; strcpy(data, rhs.data); return *this;}

粗看之下好像确实没什么问题,其实我们可以考虑的更周全点,想想,如果代码中出现了下面的语句会出现什么情况呢?

String a("Hello");a = a; //自我赋值

我们来分析下,赋值操作中,会先把自己的数据delete掉,现在rhs.data及*this.data都成了野指针,后面的strlen、strcpy操作就会产生不确定的行为。关于野指针,前面文章C/C++指针使用常见的坑(请戳我)有总结。

在这里插入图片描述

知道了问题的根源就好办了,因此,完善的写法是在前面加上一段规避自我赋值的代码,很简单,就是先判断是不是自己赋值给自己,是的话就直接返回自己就OK了。

String& String::operator=(const String &rhs){
//防止自我赋值 if (this == &rhs) {
return *this; } delete[] data; data = new char[strlen(rhs.data)+1]; strcpy(data, rhs.data); return *this;}
学如逆水行舟,不进则退

转载地址:https://chocolate.blog.csdn.net/article/details/104187697 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【C++永不过时的语言】C++11中右值引用与移动构造函数
下一篇:【C++永不过时的语言】C++关键字explicit

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月20日 02时52分35秒