如何理解C++中「引用作為函數的返回值」概念?
在慕課上修P大的C++課程時,講到了「引用作為函數的返回值」概念。有一段代碼如下:
然後輸出的結果是:
0
5
其實主要是不太理解紅框中的代碼,return *this 返回的應該是指向的這個對象,也就是main函數中的a對象。然後為什麼好像自動執行了一次構造函數,將val初始化成5?
另外想請問這種寫法的一般用在哪裡呢? 其優點又有哪些?為何不直接寫成 A a(5); ?
確實是執行了一次構造函數,但不是調用a對象的,而是通過隱式轉化生成了A的一個臨時對象,其val值為5
這裡涉及到了隱式構造函數的概念:
只有一個參數的構造函數也定義了一個隱式轉換,將該構造函數對應數據類型的數據轉換為該類對象
所以
a.GetObj()=5;
這個函數返回a的引用,等號右邊5直接調用了A類的構造函數,生成一個臨時對象,然後再賦值給a本身
如果在這個構造函數前面加上explicit關鍵字上面的語句就無法執行
class A {
public:
explicit A(int n = 0):val(n){ }
A getObj() { return *this; }
int val;
};
explicit關鍵字限定了不能有這樣的轉換髮生,所以需要將這條語句修改為
a.getObj() = A(5);
這樣就清楚了。
其實吧,你可以把引用看作一個指針(實際上它就是一個指針....)。
二者從彙編代碼的角度來看是一模一樣的:
a.GetObj() = 5;
//換成
A b = a.GetObj() ;
b = A(5);
可能理解起來就容易很多了。
------------ 詳細解釋的分割線 ------------------
a.GetObj 返回了一個對 a 的引用,它只做了這件事,沒幹別的
使用賦值符號對其賦值
class A 使用默認的 operator =,實際上這裡是 trivial 函數,bitwise copy 也成。
但是 operator 需要一個 class A 作為參數,但這是一個整型 5
需要就構造了一個臨時對象 A(5),放在等號右邊,所以調用了構造函數
然後賦值函數,然後原本 a.val 就變成了 5
然後臨時對象 A(5) 就析構了,可以加上析構輸出看下結果
------------ 結論的分割線 ------------------
這種寫法除了用來教學以外,不建議在任何工程中使用,反人類。
就題主例子里的寫法,屬於脫褲子放屁多此一舉,但是不代表這種寫法沒用.
舉個例子:
A add( int value )
{
this.val += value;
return *this;
}
這樣寫的話,就可以愉快的連續調用:
A a(5);
a.add(6).add(7);
如果不返回A, 調用一次之後就只能下一行再調用,否則編譯不過.
經常用到這種寫法
程序裡面次一級的子模塊都可以放在一個叫application的對象裡面,方便統一管理
然後用theApp.getModule()返回各個模塊的引用,來調用各個模塊的函數
沒什麼卵用的語言特性, 頂多是返回大成員用const 讓語法簡潔一點, 而單純返回還會破壞對象封裝.
引用T你可以看成一個T* const去掉一個nullptr,且這個類型的變數必須被賦值
不要這樣寫就醬
推薦閱讀:
※計算機系的高數,離散,線代都是用在哪些方面的?
※「計算」會改變信息量么?
※中文字元Unicode和UTF-8的編碼為什麼不能一樣?
※在可遇見的未來中,有什麼高科技產品將會被淘汰?