關于賦值有許多有趣的事情,其中之一就是:你可以把賦值操作連在一起:
int x, y, z;
x = y = z = 15; // 一連串的賦值
另一件有趣的事是:這一賦值工作是自右結合的,所以上面的賦值鏈可以解析成這樣:
在這里,15首先賦值給z,然后這次賦值的結果(就是更新過的z的值)將賦給y,然后這次賦值的結果(就是更新過的y的值)又賦給x。
這種實現方法的本質是:賦值時,返回一個指向運算符左手邊參數的引用,當你為你的類實現賦值運算符時,你應該遵循這一慣例:
class Widget {
public:
...
Widget& operator=(const Widget& rhs) // 返回值類型是一個指向當前類的引用,
{
...
return *this; // 返回運算符左邊的對象
}
...
};
這一慣例對于所有的賦值運算符同樣適用,不僅僅是上述的標準形式。于是,我們要這樣書寫:
class Widget {
public:
...
Widget& operator+=(const Widget& rhs)
{ // 這一慣例對于+=、-=、*=等運算符均適用
...
return *this;
}
Widget& operator=(int rhs) // 即使某些時刻運算符的參數不符合慣例,
{ // 賦值運算符仍應遵守這一慣例
...
return *this;
}
...
};
這僅僅是一個慣例,不遵循這一慣例的代碼也能夠得到編譯。然而,所有的內建數據類型,以及標準庫中所包括(或者即將包括的,可以參見條目54)的所有類型(比如說,string、vector、complex、tr1::shared_ptr,等等)都遵守這一慣例。當你要做一些有悖于該慣例的事情時先要考慮一下,是否有充分的理由這樣做?否則請遵循慣例。
時刻牢記
l 讓賦值運算符返回一個指向*this的引用。