条款15: 让operator=返回*this的引用
试图让用户自定义类型尽可能和固定类型的工作方式相似;
 固定类型赋值可以:
 
|  
      
      1 
       
     
      2 
        | 
     
     int  
       w, x, y, z; 
      w = x = y = z = 0; 
       | 
   
用户自定义类型也可以:
|  
      
      1 
       
     
      2 
        | 
     
     string w, x, y, z;  
       // string 是由标准C++库“自定义”的类型(参见条款49) 
      w = x = y = z =  
       "Hello" 
       ; 
       | 
   
 赋值运算符结合性默认是由右向左: 上面的赋值可以认为是: w = (x = (y = (z = "Hello")));
 
等价的函数形式: w.operator=(x.operator=(y.operator=(z.operator=("Hello"))));
w.operator=, x.operator=和y.operator=的参数是前一个operator=调用的返回值; 所以operator=的返回值必须作为一个输入参数被函数本身接受;
缺省版本的operator=的形式: C& C::operator=(const C&);
 一般情况下, operator=输入和返回的都是类对象的引用, 有时候需要重载operator=使它接受不同类型的参数;
 
e.g. string
|  
      
      1 
       
     
      2 
        | 
     
     string& operator=( 
       const  
       string& rhs);  
       // 将一个 string 赋给一个string 
      string& operator=( 
       const  
       char  
       *rhs);   
       // 将一个 char*赋给一个string 
       | 
   
 >即使是重载, 返回类型也要是类的对象的引用;
 
 Note C++dev 经常犯的错误是将operator=返回void, 这样妨碍了连续(链式)赋值操作;
 
另一个常犯的错误是让operator=返回const对象的引用:
|  
      
      1 
       
     
      2 
       
     
      3 
       
     
      4 
       
     
      5 
       
     
      6 
        | 
     
     class  
       Widget {
         
      public 
       : 
      ... 
           
       const  
       Widget& operator=( 
       const  
       Widget& rhs); 
      ... 
      }; 
       | 
   
 >这样做通常是为了防止程序以下的无意义操作:
 
|  
      
      1 
       
     
      2 
       
     
      3 
        | 
     
     Widget w1, w2, w3; 
      ... 
      (w1 = w2) = w3;  
       // w2 赋给w1, 然后w3 赋给其结果 (给operator=一个const 返回值 就使这个语句不能通过编译) 
       | 
   
 但是对于固定类型, 这样操作也是可以的; 所以没必要改变设定, 和固定类型的常规做法不兼容;
 
|  
      
      1 
       
     
      2 
       
     
      3 
        | 
     
     int  
       i1, i2, i3; 
      ... 
      (i1 = i2) = i3;  
       // 合法! i2 赋给i1 然后 i3 赋给i1! 
       | 
   
 
 
 缺省形式定义的赋值运算符里, 对象返回值有两个候选, 1)赋值语句左边的对象(this指针指向的对象) 2) 赋值语句右边的对象(参数表中被命名的对象);
 
|  
      
      1 
       
     
      2 
       
     
      3 
       
     
      4 
       
     
      5 
       
     
      6 
       
     
      7 
       
     
      8 
       
     
      9 
        |