2015-05-31 89 views
3

this thread很明顯,字符串文字不能用於返回常量字符串&的函數,因爲存在從const char *到std :: string的隱式轉換,從而創建臨時。返回引用臨時(內置類型)

既然這樣,爲什麼我得到一個警告「警告:返回引用到一個臨時」如果我的返回類型完全匹配,也沒有必要轉換,如:

include <iostream> 

const int& test(){ 
    return 2; 
} 

int main(){ 

    std::cout << test(); 

} 

發生不需要的隱式轉換關於2的返回值,爲什麼會有警告?我認爲使用測試()將幾乎是相同的做

const int& example = 2; 

這是完全有效的。此外,如果我將2更改爲2.2(因此它是雙精度型),程序仍然運行(具有相同的警告),儘管事實上存在從double到int的轉換?如果有從double到int的轉換,我不應該遇到類似於const char *返回到字符串引用的問題嗎?

+4

引用不能直接綁定到右值。相反,構造一個類型爲「int」的臨時對象(在'test'內部)並初始化爲2,並返回對該對象的引用。暫時在此刻被摧毀,導致參考懸而未決。 –

+0

@Igor Tandetnik我明白了,謝謝。對我而言,我鏈接的線程使得它看起來像是隻有在發生隱式轉換時纔會遇到的問題。 – Silversonic

+0

和它「有效」的「事實」,好吧,那只是UB。 –

回答

1

臨時創建仍然存在。 §8.5.3/(5.2.2.2)適用:

否則,臨時型「CV1T1」創建並從初始化表達式 副本初始化(8.5)的。然後將參考 綁定到臨時。

這也適用於你的第二個例子。它不適用於類類型,或標xvalues的prvalues:兩個

const A& a = A(); 
// and 
const int& i = std::move(myint); 

不引入一個臨時的。

的壽命: - :然而,這並不改變最終結果§12.2/(5.2)。在任何情況下,被結合到參考臨時將在return語句的末尾被破壞函數return聲明(6.6.3)中的返回值的臨時綁定不被擴展;臨時 在return 聲明中的完整表達式的末尾被銷燬。

也就是說,在函數甚至退出之前臨時被銷燬,因此你的程序會引發未定義的行爲。


我可以繼續下去,並引用整個列表,說明爲什麼這樣做,但大概是答案空間的浪費。

0

從爲const char *的隱式轉換爲std ::它會創建一個臨時

你混爲一談兩個主題字符串。隱式轉換是不是可以創建臨時對象的唯一的事情:

const std::string& test() { 
    return std::string("no implicit conversions here."); 
} 

沒有隱式轉換創建string,但創建string仍然是暫時的,所以你還是返回到臨時對象的引用。

在你的例子中,2仍然是一個臨時值,臨時存儲在堆棧的某個位置,並且其位置/地址返回,因此調用者可以獲取該值,但不應該這樣做。