2017-08-27 34 views
0

根據C++標準,在初始化引用的對象之前複製引用是否爲未定義行爲?這發生在以下示例中,其中我傳遞對父類的引用,並且僅在後面初始化對象的值,因爲對父構造函數的調用必須首先在初始化程序列表中進行。將引用複製到C++中的未初始化對象

#include <iostream> 

struct Object 
{ 
    int val; 
    Object(int i): val(i) {} 
}; 

struct Parent 
{ 
    Object& ref; 
    Parent(Object& i): ref(i){} 
}; 

struct Child : Parent 
{ 
    Object obj; 
    Child(int i): Parent(obj), obj(i) {} 
}; 

int main() 
{ 
    std::cout << Child(3).ref.val; 
} 

這裏時家長與父(OBJ)初始化的OBJ的價值還沒有被初始化。

這編譯好gcc下,我得到一個正確的輸出,但我不知道是否標準或良好的編碼實踐建議反對它。這是一個未定義的行爲?如果不是,我應該避免這是一種糟糕的做法嗎?

+2

您沒有未初始化的引用,而是對未初始化的對象的引用。這與您從標準中引用的情況不同,只要「Parent」在所有內容初始化之前都不使用引用,代碼就可以。 –

+0

謝謝,我更新了標題以反映您的評論。你說的話確實有意義,因爲它是指向未初始化對象的指針會發生什麼。 – Flynsee

+0

Bos的評論也回答了你的問題嗎?還是你編輯來澄清你問的不同之處? – Yunnosch

回答

2

首先,讓我澄清一件事。 我不確定是否可以從字面上複製參考

int i = 10; 
int& ref = i;  // since this moment ref becomes "untouchable" 
int& alt_ref = ref; // actually, means int& alt_ref = i; 

我認爲同樣的情況,如果ref是一些類的成員,你複製這個類的一個實例。另外,如果仔細觀察代碼,您甚至不會「複製引用」,而是使用未初始化(但)對象初始化引用。

struct Parent 
{ 
    Object& ref; 
    Parent(Object& i): ref(i) { } 
}; 

struct Child : Parent 
{ 
    Object obj; 
    Child(int i): Parent(obj), obj(i) { } 
}; 

物理等同於:

struct Child 
{ 
    Object& ref; 
    Object obj; 
    Child(int i): ref(obj), obj(i) { } 
}; 

有了這樣說,你的問題實際上是指:

它是不確定的行爲初始化參考 之前初始化對象它即將參考?

下面是從C++標準報價(§3.8.6[basic.life/6]),其可能給出的答案:

類似地,對象的生存期開始之前,但後該對象將佔用的存儲器已經被分配,或者在對象的生命週期結束之後並且在重新使用或釋放​​對象所佔據的存儲器之前,可以使用任何引用原始對象的glvalue,但僅可以使用該對象以有限的方式。對於正在建設或銷燬的物體 ,請參閱12.7。否則,這樣一個glvalue 引用分配的存儲(3.7.4.2),並且使用不依賴於它的值的glvalue的屬性是明確定義的。

而且§12.7.1[class.cdtor/1]只是說:

...構造之前提及任何非靜態成員或基類對象 的開始執行結果在未定義的行爲。

僅§12.7.1提到「在涉及對象成員」,因此「指的是對象本身」落在下§3.8.6。 這樣,我得出的結論是,引用未初始化(但已分配)的對象是明確的。

如果您發現任何錯誤,請在評論中告知我。也可以隨意編輯這個答案。

編輯: 我只想說,這樣的結論似乎是合理的。對象的初始化不能改變其在內存中的位置。甚至在初始化之前將已經分配的內存的引用存儲在什麼地方是不好的?

+1

第二段是問題的關鍵,實際上是答案的來源。所說的答案是「你做什麼是好的,但如果你使用提到的對象,它會中斷」。此外,它將適用於按部分標題而不是數字來引用段落。部分數字往往會有所變化,部分名稱不是很多。因此,例如[basic.life/6]而不是§3.8.6(在即將到來的C++ 17中是6.8.7)。 – StoryTeller

+0

非常感謝。正如你所說的:「可以使用但僅限於有限的方式」似乎表明,在§12.7.1之外,使用該對象是很好的。就內存管理而言,這是合理的和預期的。 – Flynsee