zoukankan      html  css  js  c++  java
  • NO.10: 在operator=中处理 "自我赋值"

    1.确保当对象自我赋值时operator=有良好的行为,其中的技术包括 "来源对象" 和 "目标对象" 的地址,精心周到的语句顺序,以及“ copy and swap ” 技术

    2.确定任何函数执行操作一个以上对象时,而其中多个对象是同一个对象时,其行为任然正确

      1 #include <iostream>
      2 
      3 
      4 //1.0
      5 class CopySwap1_0
      6 {
      7 private:
      8     int *value;
      9 public:
     10     CopySwap1_0() : value(new int(200))
     11     {}
     12 
     13     ~CopySwap1_0()
     14     { delete value; };
     15 
     16     //不符合 "C++异常安全" 1.没有考虑自赋值情况. 2.new抛出异常的话,原数据销毁
     17     CopySwap1_0 &operator=(const CopySwap1_0 &rhs)
     18     {
     19         delete value;
     20         value = new int(*rhs.value);
     21         return *this;
     22 
     23     }
     24 
     25 };
     26 
     27 //2.0
     28 class CopySwap2_0
     29 {
     30 private:
     31     int *value;
     32 public:
     33     CopySwap2_0() : value(new int(200))
     34     {}
     35 
     36     ~CopySwap2_0()
     37     { delete value; };
     38 
     39     //保证异常安全,和自赋值情况,但执行效率可以提高
     40     CopySwap2_0 &operator=(const CopySwap2_0 &rhs)
     41     {
     42         if (this == &rhs) return *this;
     43 
     44         int *temp = value;
     45         value = new int(*rhs.value);
     46         delete temp;
     47         return *this;
     48     }
     49 
     50 };
     51 
     52 
     53 //3.0
     54 class CopySwap3_0
     55 {
     56     friend void swap(CopySwap3_0& lhs,CopySwap3_0& rhs);
     57 private:
     58     int *value;
     59 public:
     60     CopySwap3_0() : value(new int(200))
     61     {}
     62 
     63     ~CopySwap3_0()
     64     { delete value; };
     65 
     66     CopySwap3_0(const CopySwap3_0& rhs)
     67     {
     68         value=new int(*rhs.value);
     69         //other work
     70     }
     71 
     72     
     73     //这样做我们会失去一个重要的优化机会
     74     //通常,我们最好遵循比较有用的规则是:不要拷贝函数参数。你应该按值传递参数,让编译器来完成拷贝工作。
     75 
     76 //    CopySwap3_0 &operator=(const CopySwap3_0 &rhs)
     77 //    {
     78 //        CopySwap3_0 lhs(rhs);
     79 //        std::swap(*this, lhs);
     80 //        return *this;
     81 //
     82 //    }
     83 
     84 
     85 //    这种管理资源的方式解决了代码冗余的问题,我们可以用拷贝构造函数完成拷贝功能,而不用按位拷贝。拷贝功能完成后,我们就可以准备交换了。
     86 //    注意到,上面一旦进入函数体,所有新数据都已经被分配、拷贝,可以使用了。这就提供了强烈的异常安全保证:如果拷贝失败,我们不会进入到函数体内,
     87 //    那么this指针所指向的内容也不会被改变。(在前面我们为了实施强烈保证所做的事情,现在编译器为我们做了)。
     88 //    swap函数时non-throwing的。我们把旧数据和新数据交换,安全地改变我们的状态,旧数据被放进了临时对象里。这样当函数退出时候,旧数据被自动释放。
     89 //    因为copy-and-swap没有代码冗余,我们不会在这个而操作符里面引入bug。我们也避免了自我赋值检测。
     90 
     91     CopySwap3_0 &operator=(CopySwap3_0 rhs)
     92     {
     93         swap(*this, rhs);
     94         return *this;
     95 
     96     }
     97 
     98 
     99 };
    100 
    101 
    102 void swap(CopySwap3_0& lhs,CopySwap3_0& rhs)
    103 {
    104     //using声明现在当前作用域寻找swap,没有则使用std::swap
    105     using std::swap;
    106     swap(lhs.value,rhs.value);
    107     //其他指针/值操作
    108 }
    109 
    110 
    111 int main(int argc, char **argv)
    112 {
    113     CopySwap3_0 A, B;
    114     A = B;
    115     return 0;
    116 }

    Toal:一般具有管理资源分配的类使用copy and swap,效益是最好的,copy and swap 使用一次拷贝构造和析构操作换取一次拷贝赋值操作(往往拷贝赋值操作也是执行析构和拷贝操作),对于数据变量结点少的情况copy and swap是最好的,也防止自赋值和异常问题,对于资源分配的类最好实现自己的swap函数,防止循环调用赋值运算符- -;

  • 相关阅读:
    被 5 整除的数
    天才的主意
    天才的主意
    谷歌浏览器 —— 快捷键(vimium:像使用 vim 一样操作当前页面)
    谷歌浏览器 —— 快捷键(vimium:像使用 vim 一样操作当前页面)
    膨胀和腐蚀操作中的不同结构元效果对比
    水果的辨异
    水果的辨异
    推理集 —— 特殊与差异
    推理集 —— 特殊与差异
  • 原文地址:https://www.cnblogs.com/xuaidongstdudyrecording/p/7260431.html
Copyright © 2011-2022 走看看