2017-07-06 92 views
0

考慮以下代碼:GCC顯示0顯示不同的值

#include <iostream> 
using namespace std; 

struct Z 
{ 
    Z() { cout << "ctor Z" << endl; } 
}; 

struct A 
{ 
    A() = default; 
    A(int xx) : x(xx) {} 
    int x; 
    Z z; 
}; 

int main() 
{ 
    A a; 
    cout << "a.x = " << a.x << endl; 
} 

與最新的GCC編譯它打印:

ctor Z 
a.x = 0 

但隨着最新鏘編譯它打印:

ctor Z 
a.x = 4198800 

爲什麼?有人可以解釋這個嗎? GCC是否發起「X」 prinitive價值,同時它並沒有做到這一點?或者,也許Clang不會用0來初始化'x',而應該這樣做呢?

當我從「A」結構中刪除我的構造函數時會發生同樣的情況,所以它不是構造函數被標記爲「默認」或類似的事情。簡單地說 - 一個編譯器生成的代碼調用其成員的構造函數作爲類對象,並且成員也是原語。另一個編譯器只運行類對象成員的構造函數。

爲什麼?

+0

見:https://stackoverflow.com/a/16782131/1526322,標準說的價值是不確定的。 GCC將其歸零。在定義之前,您不應該使用該值。您應該始終認爲該標準比編譯器更正確。 – Knox

回答

1

x正在默認初始化。綜觀http://en.cppreference.com/w/cpp/language/default_initialization

缺省初始化在三種情況下進行的:

1)時具有自動,靜態的,或線程本地存儲持續時間的變量聲明不具有初始;

2)當具有動態存儲持續時間的對象由沒有初始值設定項的新表達式創建時,或者當初始化程序由一對空括號組成的初始化程序創建的對象時創建(直到C++ 03); 3)在構造函數初始值設定項列表中沒有提及基類或非靜態數據成員,並且調用該構造函數時。

缺省初始化的效果是:

  • 如果T是一個非POD(直到C++ 11)類型,構造函數被認爲是與進行過載靠在空參數列表的分辨率。所選的構造函數(這是默認構造函數之一)被調用來爲新對象提供初始值;

  • 如果T是一個數組類型,則該數組的每個元素都是默認初始化的;

  • 否則,不做任何事情:具有自動存儲持續時間(及其子對象)的對象被初始化爲不確定的值。

+0

這解決了我的問題,謝謝。所以,據我所知,'Z'的構造函數被稱爲是因爲它是一個非POD,並且'x'由於第三個子項「否則」而未被初始化,對吧? – YotKay

+0

對於Z,項目3適用 – Amadeus

+0

項目3用於Z?第3項說沒有做任何事情,而Z的構造函數被調用。 – YotKay

3

你需要在每一個構造函數初始化x,不只是其中之一。使用默認構造函數會使其未初始化。 GCC可能會將其歸零,或者在啓動過程時將其清零。 clang在這裏做垃圾數據;它顯示有一個錯誤。

你可以如此修正:

A(int xx = 0) : x(xx) {} 

如果不再需要其他的構造函數,因爲您提供的默認值。

+1

0就像「垃圾」一樣。海灣合作委員會的行爲正如「正確」。 –

+1

另一種選擇:OP可以添加一個默認的初始化程序:'int x = 0;'。 – HolyBlackCat

+0

或者說'A a {};' – juanchopanza

2

不同的編譯器生成不同的代碼應該不會感到意外。否則只會有一個編譯器。

它們之間的區別在處理未定義行爲的實例時尤爲明顯,例如讀取未初始化對象的不確定「值」(例如,在此爲A::x)。

對於爲什麼特定的編譯器在這裏具體產生具體的值,這是非常複雜和毫無意義的理由,因爲有非常多的可能的解釋,所有這些解釋都可能在下一次你點擊「編譯」時改變。討論when an implementation fills a memory space with e.g. 0xCCCCCCCC in debug mode更容易,因此當您忘記初始化某些內容時,您可以查看。雖然這兩種情況都沒有發生。