NO.10: 在operator=中处理 "自我赋值"
1.确保当对象自我赋值时operator=有良好的行为,其中的技术包括 "来源对象" 和 "目标对象" 的地址,精心周到的语句顺序,以及“ copy and swap ” 技术
2.确定任何函数执行操作一个以上对象时,而其中多个对象是同一个对象时,其行为任然正确
#include <iostream> //1.0
class CopySwap1_0
{
private:
int *value;
public:
CopySwap1_0() : value(new int())
{} ~CopySwap1_0()
{ delete value; }; //不符合 "C++异常安全" 1.没有考虑自赋值情况. 2.new抛出异常的话,原数据销毁
CopySwap1_0 &operator=(const CopySwap1_0 &rhs)
{
delete value;
value = new int(*rhs.value);
return *this; } }; //2.0
class CopySwap2_0
{
private:
int *value;
public:
CopySwap2_0() : value(new int())
{} ~CopySwap2_0()
{ delete value; }; //保证异常安全,和自赋值情况,但执行效率可以提高
CopySwap2_0 &operator=(const CopySwap2_0 &rhs)
{
if (this == &rhs) return *this; int *temp = value;
value = new int(*rhs.value);
delete temp;
return *this;
} }; //3.0
class CopySwap3_0
{
friend void swap(CopySwap3_0& lhs,CopySwap3_0& rhs);
private:
int *value;
public:
CopySwap3_0() : value(new int())
{} ~CopySwap3_0()
{ delete value; }; CopySwap3_0(const CopySwap3_0& rhs)
{
value=new int(*rhs.value);
//other work
} //这样做我们会失去一个重要的优化机会
//通常,我们最好遵循比较有用的规则是:不要拷贝函数参数。你应该按值传递参数,让编译器来完成拷贝工作。 // CopySwap3_0 &operator=(const CopySwap3_0 &rhs)
// {
// CopySwap3_0 lhs(rhs);
// std::swap(*this, lhs);
// return *this;
//
// } // 这种管理资源的方式解决了代码冗余的问题,我们可以用拷贝构造函数完成拷贝功能,而不用按位拷贝。拷贝功能完成后,我们就可以准备交换了。
// 注意到,上面一旦进入函数体,所有新数据都已经被分配、拷贝,可以使用了。这就提供了强烈的异常安全保证:如果拷贝失败,我们不会进入到函数体内,
// 那么this指针所指向的内容也不会被改变。(在前面我们为了实施强烈保证所做的事情,现在编译器为我们做了)。
// swap函数时non-throwing的。我们把旧数据和新数据交换,安全地改变我们的状态,旧数据被放进了临时对象里。这样当函数退出时候,旧数据被自动释放。
// 因为copy-and-swap没有代码冗余,我们不会在这个而操作符里面引入bug。我们也避免了自我赋值检测。 CopySwap3_0 &operator=(CopySwap3_0 rhs)
{
swap(*this, rhs);
return *this; } }; void swap(CopySwap3_0& lhs,CopySwap3_0& rhs)
{
//using声明现在当前作用域寻找swap,没有则使用std::swap
using std::swap;
swap(lhs.value,rhs.value);
//其他指针/值操作
} int main(int argc, char **argv)
{
CopySwap3_0 A, B;
A = B;
return ;
}
Toal:一般具有管理资源分配的类使用copy and swap,效益是最好的,copy and swap 使用一次拷贝构造和析构操作换取一次拷贝赋值操作(往往拷贝赋值操作也是执行析构和拷贝操作),对于数据变量结点少的情况copy and swap是最好的,也防止自赋值和异常问题,对于资源分配的类最好实现自己的swap函数,防止循环调用赋值运算符- -;
NO.10: 在operator=中处理 "自我赋值"的更多相关文章
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to sel ...
- 条款11:在operator=中处理“自我赋值”
什么是自我赋值,就是 v = v 这种类型的语句,也许很多人都会说鄙视这种写法,但是如下的写法会不会出现呢? 比如:a[i] = a[j]; // 不巧的是i可能和j相等 *px = *py ...
- 【11】在operator=中处理“自我赋值”
1.自我赋值,看起来愚蠢,但是却合法.有些自我赋值一眼就可看出来.有些自我赋值是潜在的.比如:a[i] = a[j]; *px = *py; 甚至不同类型的指针,都指向同一个地址,也是自我赋值,这一类 ...
- Effective C++_笔记_条款11_在operator=中处理“自我赋值”
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为什么会出现自我赋值呢?不明显的自我赋值,是“别名”带来的结果: ...
- Effective C++ 条款11:在operator=中处理"自我赋值"
"自我赋值"发生在对象被赋值给自己时: class Widget { ... }; Widget w; ... w = w; // 赋值给自己 a[i] = a[j]; // 潜在 ...
- Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分
1.潜在的自我赋值 a[i] = a[j]; *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...
- Effective C++ -----条款11: 在operator=中处理“自我赋值”
确保当对象自我赋值时operator=有良好行为.其中技术包括比较“来源 对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap. 确定任何函数如果操作一个以上的对象,而其中多 ...
- [Effective C++ --011]在operator=中处理“自我赋值”
一.何谓“自我赋值”? 1.1.场合一 直接赋值 w = w; 1.2.场合二 同一数组 a[i] = a[j]: 1.3.场合三 指针 *px = *py: 1.4. ...
- EC读书笔记系列之6:条款11 在operator=中处理自我赋值
记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...
随机推荐
- SpringMVC-RESTRUL___CRUD知识点总结
RESTful风格 <!-- 携带surveyId去后台 --><!-- RESTFUL风格:/xxx/23 --><!-- 接收方式:@PathVariable注解 - ...
- PAT 1016 部分A+B
https://pintia.cn/problem-sets/994805260223102976/problems/994805306310115328 正整数A的“D~A~(为1位整数)部分”定义 ...
- Linux 忘记root密码
1 将系统重启,读秒的时候按下任意键就会出现如下图菜单界面 2 进入上图菜单界面之后,按e键就可以进入grub的编辑模式 3 选择第二行 kernel开头,再按 e 键进入该行的编辑界面中,然后在出现 ...
- dotnet core的下载地址 以及sdk和runtime的 version 简单说明
1. dotnet core 2.1 的下载地址 https://dotnet.microsoft.com/download/dotnet-core/2.1 2. dotnet core 2.2 的下 ...
- Windows 安装 docker 以及1709的简单使用
PS C:\> Install-Module -Name DockerMsftProvider -Repository PSGallery -Force PS C:\> Install-P ...
- 基于C#.NET的高端智能化网络爬虫(一)(反爬虫哥必看)
前两天朋友发给我了一篇文章,是携程网反爬虫组的技术经理写的,大概讲的是如何用他的超高智商通过(挑衅.怜悯.嘲讽.猥琐)的方式来完美碾压爬虫开发者.今天我就先带大家开发一个最简单低端的爬虫,突破携程网超 ...
- python slots
正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Studen ...
- js實現
js的代碼寫在<script></script>中: <script></script>可以放在body中或者head中,如果放在body中,一般放在b ...
- js跨域请求jsonp解决方案-最简单的小demo
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- 微软爱开源:向Linux社区开放60000多项专利
10月10日,微软在博客中宣布正式加入开放创新网络(Open Invention Network, 简称“OIN”),向所有开源专利联盟的成员开放其专利组合. 微软的加入意味着,旗下60000多项专利 ...