为了账号安全,请及时绑定邮箱和手机立即绑定

没有学不会的C++:复制操作符怎么写

标签:
C++

C++ 中的操作符重载可以让我们的代码更符合人们的阅读习惯,而 operator= 赋值操作符又是最常被重载的操作符。本篇主要谈到我们在写 operator= 时可能会遇到的复制相同对象的问题,及我们该如何解决它。

对于「复制自己」,你肯定不会写这样的代码

Dog a;
a = a;

但你可能会写这样的代码

dogs[i] = dogs[j];

而当 ij 相等时,你便无意间写出了「复制自己」的代码,但到底「复制自己」会出现什么问题呢?先来看下下面这段代码:

class Collar{};
class Dog {
    Collar* pCollar;
    
    Dog& operator=(const Dog& rhs) {
        delete pCollar;
        pCollar = new Collar(*rhs.pCollar);
        return *this;
    }
};

上面这段赋值操作符的实现,首先就把指针 pCollar 给释放了,如果传入的对象就是自己,那么 pCollar = new Collar(*rhs.pCollar) 这一行中的 rhs.pCollar 就会引用一个被释放的指针,这会对程序造成灾难性的结果。

于是,为避免「复制自己」的问题,我们可以在 delete 之前加一个条件判断,如下

// ...
    Dog& operator=(const Dog& rhs) {
        if (this == &rhs) {
            return *this;
        }
        
        delete pCollar;
        pCollar = new Collar(*rhs.pCollar);
        return *this;
    }
// ... 

但这还没完,这里还有一个漏洞,如果 new Collar(*rhs.pCollar) 抛出异常,则该对象的 pCollar 由于被释放了,而变成了一个”野指针“,这也会给程序带来无法预期的结果。所以更为安全的写法是这样的:

// ...
    Dog& operator=(const Dog& rhs) {
        if (this == &rhs) {
            return *this;
        }
        
        Collar* pOriginCollar = pCollar;
        pCollar = new Collar(*rhs.pCollar);
        delete pOriginCollar;
        return *this;
    }
// ...

可以看到,即便 new Collar 抛出了异常,pCollar 所指向的内容仍然不变。

此外,我们还有另外一种解决「复制自己」的方案,即面向对象中常用的委派(delegate),例如这里要复制的 Collar 对象,不是在宿主 Dog 对象中完成,而是把复制的动作委派给 Collar 的复制构造函数去完成,这样做的好处是各个类的代码各司其职,复杂度降低,更不易出错,如下:

class Collar {
    int price;
public:
	Collar &operator=(const Collar& rhs) {
    	if (this == &rhs) {
        	return *this;
    	}
    	price = rhs.price;
    	return *this;
	}
};

class Dog {
    Collar* pCollar;
    Dog& operator=(const Dog& rhs) {
        *pCollar = *rhs.pCollar; // member by member copy of Collars
        return *this;
    }
};

以上,请记住一点

在写复制操作符时,要避免复制自己。

参考:

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消