原文地址:http://www.vckbase.com/index.php/wv/219
[問題的提出]: 在很多書籍和文章中,很多次提到在對賦值操作符(=)進行重載的時候,要返回對目的(調用)對象實例(*this)的引用。其中不免有這樣的論斷:一定要返回對調用對象的引用;返回對調用實例對象的引用是爲了實現鏈式連續賦值。 這裏說明兩個問題:第一,是否重載賦值操作符必須返回對調用對象的引用,第二,是否這樣就可以實現鏈式賦值,而不這樣就不行。 首先,必須承認,返回對"*this"的引用是標準的二目操作符重載的格式,效率很高。這樣做有很多優點:如實現鏈式賦值、避免臨時對象的產生(調用拷貝構造函數)、銷燬(調用析構函數),但不是非這樣做不可,下面通過對比來論述返回對"*this"的引用的優點及其他做法的缺點,同時也能清楚第二個問題,我們從例子着手。 01. //
a.h 02. class A 03. { 04. public : 05. A(); 06. A( int nTest); 07. A( const A&
a); 08. virtual ~A(); 09. A
operator=( const A&
a); 10. //
A& operator=(const A& a); 11. 12. private : 13. int m_nTest; 14. 15. public : 16. void printit(); 17. }; 18. } 19. 20. //
a.cpp 21. A::A( int nTest) 22. { 23. m_nTest
= nTest; 24. cout
<< "constructor
A Value is executed now!" <<
endl; 25. } 26. 27. A::A( const A&
a) 28. { 29. this ->m_nTest
= a.m_nTest; 30. cout
<< "Copy
constructor A is executed now!" <<
endl; 31. } 32. 33. A::A() 34. { 35. cout
<< "constructor
A Default is executed now!" <<
endl; 36. } 37. 38. A::~A() 39. { 40. cout
<< "Destructor
A is executed now!" <<
endl; 41. } 42. A
A::operator=( const A&
a) 43. //
A& A::operator=(const A& a) 44. { 45. if ( this ==&a) 46. return * this ; 47. this ->m_nTest
= a.m_nTest; 48. cout
<< "Assignment A is 49. executed
now!" << endl; 50. return * this ; 51. } 在main()函數中調用 1. A
a(100),b(99),c(98); 2. a
= b = c; 3. a.printit(); 4. b.printit(); 5. c.printit(); 結果爲:
如果將 A operator=(const A& a) 改爲 A& operator=(const A& a)
兩者的不同爲前者比後者多執行了兩次構造(拷貝構造函數)和析構函數,可見在執行過程充產生了兩個臨時對象。 [1]在賦值函數爲:A operator=(const A& a)的情況下 對於a=b=c; 實際爲a.operator=(b.operator=(c)) 在執行A operator=(const A& a) 後返回 *this 給一個臨時對象,所以生成和銷燬這個臨時對象的時候分別要調用構造和析構函數,而構造時是用一個已經存在的實例出初始化同類型的實例,所以調用的拷貝初始化函數。析構時,先析構前面一個(a.operator=)產生的臨時對象,後析構"b.operator="產生的臨時對象. [2] 在賦值函數爲:A& operator=(const A& a)的情況下 不同的是沒有臨時對象的產生,因爲operator=返回的是對當前對象的引用,而引用只是別名,而不是構造新對象的。這點可以通過如下函數調用來理解: 1. void fun(A&
temp) 2. { 3. temp
... 4. } 5. A
a; 執行fun(a)函數調用時,沒有產生臨時對象。 可見,重載"="操作符,不一定要返回對賦值目的對象的引用,但返回引用是很好的做法,建議您這樣使用。 最後提出幾個問題,大家可以思考一下: [1] 若將a=b=c; 改爲(a=b)=c後分別調用A operator=(const A& a) 和A&operator=(const A& a)結果會有什麼不同? [2] 能否將A&operator=(const A& a)改爲const A&operator=(const A& a)? [3] 能否將A&operator=(const A& a)中的return *this;改爲return a? [4] A a, b; a = b; 與 A a; A b = a; 有什麼不同? 水平有限,歡迎大家批評指正! |
【1】調用A operator = (const A& a ),結果爲
【2】可以。
【3】不能 原因:不能將類型爲‘A&’的非 const 引用初始化爲類型爲‘const A*’的臨時變量
【4】
說明:上面爲A a,b; a=b的結果;下面爲A a; A b = a;的結果。上面分別調用了兩次默認構造函數和一次賦值操作;
下面調用一次默認構造函數和一次帶參數的構造函數。