2014-04-03 146 views
11

我們不能寫int& ref = 40,因爲我們需要lvalue在右側。但我們可以寫const int& ref = 40。爲什麼這可能? 40 is rvalue instead lvalue強制參考和左值

我知道這是一個例外,但爲什麼?

+0

絕對是一個騙局。 –

回答

10

作爲Stroustrup的說:

爲一個constŤ&初始化器不必是一個左值或者甚至 類型T.在這種情況下:

[1]首先,隱式類型轉換到必要時應用T.

[2]然後,將所得的值被置於

[3]最後,本臨時變量被用作 初始化的值 類型T的臨時變量。

因此,當您鍵入const int& ref = 40時,臨時int變量在幕後創建,並且ref被綁定到此臨時變量。

11

該語言中有一條規則允許將常量左值引用綁定到右值。該規則的主要理由是,如果它不存在,那麼你就必須提供的功能,不同的重載能夠使用的臨時對象參數:

class T; // defined somewhere 
T f(); 
void g(T const &x); 

有了這條規則,你可以做g(f()) ,如果沒有它,才能夠做到這一點,你需要創建一個不同的g重載需要一個右值(這是從時間,其中右值引用,甚至沒有在語言!)

+0

我仍然不確定爲什麼[生命週期延長](http://stackoverflow.com/q/20546981/596781),雖然:-( –

+0

@KerrekSB:我想最初的原因是這樣你可以寫'T const&_ = ...;'或'T const _ = ...;無所謂,兩者都可以工作,前者在表達產生參考時更有效率(無副本)。這是相當可惜了,雖然,因爲它可以讓很多的擊打在 –

+1

@KerrekSB滑。我想我已經在鏈接的問題,解決這一點。這是允許在通用上下文中進行綁定的副作用(不僅在函數參數中),也不希望它在每次使用時都導致未定義的行爲。如果沒有生命週期的延伸:'T const&x = f();'後面跟*任何* odr-x的使用都是未定義的行爲,引發了爲什麼要放在第一位的問題?因此,無論是否提供一致性(引用都綁定在任何*上下文中)和終生擴展,或者您接受不一致,並且不需要終生擴展。該語言的前者。 –

2

爲什麼有可能嗎?

40是這裏的文字。常量引用可以用文字和臨時對象來初始化,以延長它們的使用壽命。

int const& ans = 40; 
// transformed: 
int __internal_unique_name = 40; 
int const& ans = __internal_unique_name; 

另一種情況是,當你有一個功能,例如:這可以通過編譯器來完成這樣

void f(std::string const& s); 

,你想用

f("something"); 

這叫它臨時變量只能綁定到const引用。

+1

這也是與非const引用的情況下... –

+0

@DavidRodríguez-dribeas不是第二種情況提供 – 4pie0

+0

這正是編譯器會爲你做,它調用映射到:'的std :: string __tmp(」東西「); F(__ TMP);'。這是*,因爲你可以*不是爲'const'引用(* alone *)允許這麼做的原因,事實證明,Solaris CC和VS通過完全相同的方式支持對臨時對象的非const引用的綁定事情。 –

1

您可以將右值綁定到const引用。該語言保證綁定對象的存在直到引用的範圍結束,甚至靜態調用正確的析構函數。這是例如在ScopeGuard實現(http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2)中使用,使其具有類似虛擬析構器的行爲,而無需支付虛擬方法調用。

+0

編譯器沒有選擇萬年此事。語言規則決定了生活時間。 –