【11】在operator=中处理“自我赋值”
2014-01-20 20:35
351 查看
1、自我赋值,看起来愚蠢,但是却合法。有些自我赋值一眼就可看出来。有些自我赋值是潜在的。比如:a[i] = a[j]; *px = *py; 甚至不同类型的指针,都指向同一个地址,也是自我赋值,这一类自我赋值,很难识别,因此对自我赋值要有一定的防范。
2、对于资源管理类auto_ptr和shared_ptr,自我赋值是安全的。如果自行管理资源,比如Widget中有个Bitmap* pb;copy赋值如下:
假如是自我赋值,delete销毁了this.pb,也是销毁了rhs.pb,rhs.pb指向垃圾,new出来的Bitmap也有问题。
3、怎么解决上面的问题,增加一个等同测试,如下:
4、上面的方法还是有问题,考虑new Bitmap的时候出现异常,这种情况下,老的对象已经销毁,新的又没有分配成功,导致pb指向垃圾。怎么解决这个问题呢?
问题的关键是,先删除老的,再去分配新的。因此,可以这样解决:先把老的记录下来,再去分配新的,然后再去删除老的,如果分配新的出现异常,退出方法,老的没有删除,还是原来的值。如下:
5、再仔细分析一下,上面不需要等同测试,即使相同也是没有问题的,只不过导致Bitmap的copy构造。这种情况下,考虑等同测试的成本和Bitmap copy构造的成本,如果等同的频率很高,添加等同测试,否则去掉等同测试。
6、有没有更好的办法呢?
既然可能出现自我赋值,我可以先对rhs做个copy temp,然后this和temp交换,这样也就不需要考虑自我赋值了。特别注意:下面的交换只是交换指针值,并不交换指向的内容,可以认为是浅交换。
7、上面的做法还可以优化,形参表中使用传值,方法内直接使用swap(rhs); 这种方法很好地利用了传值的特点,具有技巧性,但是失去了清晰性,不推荐这种做法。
2、对于资源管理类auto_ptr和shared_ptr,自我赋值是安全的。如果自行管理资源,比如Widget中有个Bitmap* pb;copy赋值如下:
Widget& Widget::operator=(const Widget& rhs) { delete pb; pb = new Bitmap(*(rhs.pb)); return *this; }
假如是自我赋值,delete销毁了this.pb,也是销毁了rhs.pb,rhs.pb指向垃圾,new出来的Bitmap也有问题。
3、怎么解决上面的问题,增加一个等同测试,如下:
Widget& Widget::operator=(const Widget& rhs) { if(this == &rhs) { return *this; } delete pb; pb = new Bitmap(*(rhs.pb)); return *this; }
4、上面的方法还是有问题,考虑new Bitmap的时候出现异常,这种情况下,老的对象已经销毁,新的又没有分配成功,导致pb指向垃圾。怎么解决这个问题呢?
问题的关键是,先删除老的,再去分配新的。因此,可以这样解决:先把老的记录下来,再去分配新的,然后再去删除老的,如果分配新的出现异常,退出方法,老的没有删除,还是原来的值。如下:
Widget& Widget::operator=(const Widget& rhs) { if(this == &rhs) { return *this; } Bitmap* old = pb; pb = new Bitmap(*(rhs.pb)); delete old; return *this; }
5、再仔细分析一下,上面不需要等同测试,即使相同也是没有问题的,只不过导致Bitmap的copy构造。这种情况下,考虑等同测试的成本和Bitmap copy构造的成本,如果等同的频率很高,添加等同测试,否则去掉等同测试。
6、有没有更好的办法呢?
既然可能出现自我赋值,我可以先对rhs做个copy temp,然后this和temp交换,这样也就不需要考虑自我赋值了。特别注意:下面的交换只是交换指针值,并不交换指向的内容,可以认为是浅交换。
Widget& Widget::operator=(const Widget& rhs) { Widget temp(rhs); swap(temp); return *this; }
7、上面的做法还可以优化,形参表中使用传值,方法内直接使用swap(rhs); 这种方法很好地利用了传值的特点,具有技巧性,但是失去了清晰性,不推荐这种做法。
相关文章推荐
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
- effective C++ 11_在operator= 中处理"自我赋值" 读书笔记
- 条款11:在operator=中处理“自我赋值
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
- C++中在operator=中处理“自我赋值”(11)---《Effective C++》
- tip11:在operator=中处理自我赋值
- 条款11:在operator=中处理“自我赋值”(Handle assignment to self in operator=.)
- effective c++条款11 在operator=中处理“自我赋值”
- Effective C++ Item 11-在operator = 中处理"自我赋值"
- 条款11 在operator=中处理“自我赋值”
- 在operator=中处理自我赋值(Effective C++_11)
- 条款11: 在operator= 中处理"自我赋值"
- 条款11:在operator=中处理“自我赋值”
- effective c++ Item 11 在operator=中处理自我赋值
- 条款11:在operator = 中处理"自我赋值"
- 条款11:在operator = 中处理“自我赋值”
- 条款11:在operator=中处理“自我赋值”
- 条款11:在operator= 中处理“自我赋值”
- 读书笔记《Effective c++》 条款11 在operator= 中处理“自我赋值”
- Effective C++ 条款10 令operator=返回一个reference to *this 条款11 在operator=中处理"自我赋值"