2015-11-16 51 views
5

Clang編譯器生成警告編譯此代碼段,我找不出原因。指針解引用返回引用本地臨時對象

const int* Get() { 
    static const int ARRAY[4] = {1, 2, 3, 4}; 
    return &ARRAY[0]; 
} 

const int& Test() { 
    const auto& p = Get(); 
    return (*p); 
} 

warning: returning reference to local temporary object [-Wreturn-stack-address] 
    return (*p); 

GCC在此代碼上未顯示警告。 我可以解決這樣的片段:const auto p = Get(); 但我想知道是否有一些臨時的對象,問題在於更深

+0

@ 101010「臨時對象」?也許你可以更清楚一點?我們絕對可以引用堆棧中的非const變量。 –

+4

鑑於'p'是一個臨時的,'* p'是有效的。我認爲這是Clang的誤判。 – Jarod42

+1

@JonathanMee:[瞭解臨時工](http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/) –

回答

4

這一警告是假陽性,因爲p指向者不是一個暫時的,儘管p指到一個。有更多的情況是虛假地產生這種警告的;見例如Bug 21218,它採用

char * f() { 
    typedef char* t; 
    const t & r = new char[5]; 
    return r; 
} 

據推測,如果返回類型是一個參考,鏘查找常量引用在返回的表達式(已綁定到臨時工),沒有考慮如何使用它們。

1

答:Clang的警告是不正確的。

讓我們一步步通過什麼這裏發生的情況:

  1. static const int ARRAY[4] = {1, 2, 3, 4};構建的int小號
  2. return &ARRAY[0];一個全局數組返回一個指向全局數組的第一個元素
  3. const auto& p = Get()存儲參照指針到全局數組的第一個元素
  4. return (*p);創建對全局數組第一個元素的左值的引用

是個棘手的問題。鏗鏘似乎錯誤地認爲*p是一個本地價值,事實上我們知道它是一個全球性的。

這個證明的關鍵是the fact that *p returns an lvalue

+0

_「這很容易做到」,因爲它在標準中說得很清楚。 –

+0

@LightnessRacesinOrbit我自己沒有該標準的副本,而且我似乎無法找到任何確認解除引用操作符返回了左值的任何在線信息。如果你能指出我的來源,我很樂意將其列入,而不是一個例子來證明我的答案。 –

+1

https://en.wikipedia.org/wiki/Dereference_operator第二句 –