2016-07-15 38 views
2

考慮:初始化列表和const& - 這是合法的C++

#include <iostream> 
#include <vector> 

class A 
{ 
public: 
    const int& i;  
}; 

class B 
{ 
public: 
    const std::vector<int>& i; 
}; 

int main() 
{ 
    A a = { 3 }; 
    std::cout << a.i << std::endl; 

    B b = { { 1, 2 } }; 
    std::cout << b.i[0] << " " << b.i[1] << std::endl; 
} 

在VS2015更新3,這個崩潰在運行時在最後一行,因爲矢量b.i是空的;在gcc(4.9.2)上運行OK並顯示預期的輸出(3 1 2)。所以在VS它'工作'(我所期望的)爲一個int,但不是一個向量。

這是VS錯誤還是它只是一個意外,它在gcc上工作?

+2

這很明顯是未定義的行爲。你有參考資料綁定到暫時被破壞的臨時對象。 「似乎工作」是UB的一種可能的表現形式。 –

+0

我不認爲這是http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of--temporary的重複。這個問題涉及到構造函數的調用,但是這個是關於聚合初始化的。 – cpplearner

+0

標準草案實際上有一個類似的[示例](http://www.eel.is/c++draft/class.temporary#6):struct S {int mi; const std :: pair & mp;}; S a {1,{2,3}};'。 – cpplearner

回答

1

第一個是確定的,臨時的生命週期在分配給參考時被擴展。其次是UB AFAIK,因爲{ { 1, 2 } }std::initializer_list<>,而不是std::vector<>直接。延長生命週期臨時對象不是傳遞性的(即它持續到當前0​​函數結束,在這種情況下是構造函數),只有本地變量延長。

1

它在gcc上工作不小心,因爲這肯定是未定義的行爲。

爲了滿足B的初始化,編譯器需要構造一個臨時的vector<int>。由於對該向量的引用是const,編譯器在使用它初始化B時看不到問題。但是,臨時對象一旦初始化結束就會失效,因此在初始化之外通過引用訪問它是未定義的行爲。