首先定義類Person
class Person{ public: string name; Person()=default; //默認構造函數 Person(string nam):name(nam){} void operator=(const Person& p){ //賦值構造函數 this->name=p.name; } }; Person a("xiaoming"); Person b; cout<<b.name<<endl; //空 b=a;//執行賦值構造函數 cout<<b.name<<endl; //xiaoming
由上,賦值操作已完成,可為什么賦值構造函數還有個返回值
為什么有返回值?(初學者可能不理解b=a為什么會產生返回值)
首先b並不接收返回值(b=a讓某些初學者誤認為b接受返回值)
其實只要把b=a 看成是 a.operator=(b)就可以了
b=a的返回值就相當於a.operator=(b)這個函數的返回值
比如
我們來修改賦值構造函數返回值為一個具體的整數100
int operator=(const Person& p) { this->name = p.name; return 100; } cout<<10+(b=a)<<endl; // 110
結果,(b=a)產生了一個臨時變量100,然后這個臨時變量和10相加得結果110,這個臨時變量就是我們所謂的返回值
那返回值到底有什么用呢?
可以讓對象進行鏈式操作
比如我們將返回值更改為這個對象的引用
Person& operator=(const Person& p) { this->name = p.name; return *this; } Person& showName() { cout<<this->name; return *this; } (b=a).showName(); //xiaoming
我們在給b賦值以后還能再讓其還能再執行函數showName
那返回值是引用類型和非引用類型有區別嗎?
區別當然大了
1.對一個對象進行兩次連續的賦值操作
首先新建一個對象c
Person c("huanghuang");
1)賦值構造函數返回值是引用類型
(b=a)=c;
cout<<b.name<<endl; //huanghuang
2)賦值構造函數返回值不是引用類型
(b=a)=c;
cout<<b.name<<endl; //xiaoming
可以看到結果不同,究其原因,第2)種情況讓系統拷貝了一份臨時變量,因而是c給臨時變量賦值,而非對象b
表一 結果對比表
返回值類型 (b=a)執行后產生的結果
Person& b的引用
Person b的一份拷貝(臨時變量)
擴展閱讀:
臨時變量又叫做右值,左值就是非臨時變量
詳細解釋:( https://blog.csdn.net/thisinnocence/article/details/23883483 https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ https://blog.csdn.net/zhangsj1007/article/details/79940370【三篇關於左值右值的講解】)
粗糙解釋:就是在執行某段代碼中間產生的臨時變量,這個臨時變量在執行完這段代碼后就會被析構,除非你引用了這個臨時變量。
//如果返回值類型不為引用 產生了臨時變量 我們引用這個臨時變量
Person&& d=b=a;
Person&用於引用一個已經被定義好的Person對象
Person&&則是用於引用一個臨時的Person對象(認領這塊無主之地)
2.將一個對象連續賦值給兩個對象
即a=b=c
首先我們增加一個拷貝構造函數 再給賦值構造函數增加一個輸出
Person(const Person&p) { cout<<"copy constructor"<<endl; } Person& operator=(const Person& p) { cout << "copy assignment constructor" << endl; this->name = p.name; return *this; }
a=b=c;
1)賦值構造函數返回值為引用類型
copy assignment constructor
copy assignment constructor
2)賦值構造函數返回值為非引用類型
copy assignment constructor
copy constructor
copy assignment constructor
copy constructor
我們看到賦值構造函數返回值為非引用類型時,導致系統為其拷貝生成兩個臨時變量
雖然最后達到的目的一致,但是增加了內存開支