如何理解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的編碼為什麼不能一樣?
在可遇見的未來中,有什麼高科技產品將會被淘汰?

TAG:編程 | 計算機科學 | C | CC |