Item 11 赋值函数的自赋值

本文探讨了C++中自我赋值的问题,并提出了几种解决方法,包括简单的身份测试、改进的赋值流程以及copy-and-swap策略。这些方法有助于确保赋值操作的安全性和异常安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class Widget { ... }; Widget w; ... w = w; // 1. 能通过编译,但是明显不合理! ... a[i] = a[j]; // 2. ij可能相同 *px = *py; // 3. 二者可能相同或有继承关系

上面的三种情况,都是给自己赋值,要在赋值时检查。

class Bitmap { ... }; class Widget { ... private: Bitmap *pb; }; // 既无赋值安全性,又无异常安全性的函数 Widget& Widget::operator=(const Widget& rhs) { delete pb; // 未检查是否自我赋值就释放了资源 pb = new Bitmap(*rhs.pb); // 如出现异常,pb就指向了无效内存 return *this; }

改正的办法:

1> 检查自赋值情况:

// 至少做到了赋值安全性 Widget& Widget::operator=(const Widget& rhs) { if (this == &rhs) return *this; // identity test delete pb; ...

2> 改流程:

// 赋值安全、异常安全,都考虑到了,只是在自赋值的时候效率低些 Widget& Widget::operator=(const Widget& rhs) { Bitmap *pOrig = pb; pb = new Bitmap(*rhs.pb); // 若出现异常也不会影响pb,安全 delete pOrig; // 前面都成功了,再释放原来的资源 return *this; }

如果想把 identity test 加上,那么还要考虑自赋值的频率。频率小的话反而会降低效率,因为会影响CPU的prefetching、caching和pipelining。

3> copy and swap

class Widget { ... void swap(Widget& rhs); ... }; Widget& Widget::operator=(const Widget& rhs) { Widget temp(rhs); swap(temp); return *this; }

有时为了优化效率,而采用传值的方式:

Widget& Widget::operator=(Widget rhs) { swap(rhs); return *this; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值