2014-10-04 56 views
1

我不明白以下兩個語句之間的區別:「事情」有什麼區別?和「Thing thing = Thing();」,我應該什麼時候使用一個呢?

Thing thing; 

Thing thing = Thing(); 

兩個創建Thing對象,並把它放在變量thing,對不對?如果是這樣,兩個問題:

1-兩者之間的技術差異是什麼?

2-什麼時候應該使用另一個?

請注意:

A-我沒有使用C++ 11

B-新的C++,請使用新手友好的話。

+1

首先一個默認初始化。第二個有效的價值初始化。 – 2014-10-04 10:20:44

+0

應該有一個重複的.. – 2014-10-04 10:22:34

+0

請參閱[cppreference的初始化](http://en.cppreference.com/w/cpp/language/initialization)頁面瞭解更多信息。 – 2014-10-04 10:24:14

回答

0

不同之處在於,如果複製或移動構造函數不可訪問,編譯器可能會爲第二個定義發出錯誤。例如,他們可能被定義爲私人或刪除。

Thing thing; 

Thing thing = Thing(); // there may be a compiler error 

例如考慮下面的方案

int main() 
{ 
    class A 
    { 
    private: 
     A(const A &); 
    public: 
     A() {} 
    }; 

    A a; 

    return 0; 
} 

上述程序將successfuly編譯而下面的程序將不被編譯(如果僅編譯不例如MS VC++ 2010)

int main() 
{ 
    class A 
    { 
    private: 
     A(const A &); 
    public: 
     A() {} 
    }; 

    A a = A(); 

    return 0; 
} 

另一個不同是,在此聲明

A a; 

一個是默認初始化

而在此聲明

A a = A(); 

被值進行初始化。

從C++標準

2所述的表達T(),其中T是一個簡單的類型說明符或 類型名稱說明符用於非陣列的完整對象類型或 (可能CV-合格的)void類型,創建一個指定的 類型的值,其值是通過對類型T進行值初始化(8.5) 對象產生的值;沒有爲void()情況進行初始化。

考慮另一個示例

int main() 
{ 
    class A 
    { 
     int x; 
    }; 

    A a1; 
    A a2 = A();  

    return 0; 
} 

對於x的A1值將是未指定的,同時將s2 x的值將等於0。

+0

所以一般情況下,我應該使用'A a;',而不是'A a = A();'? – 2014-10-04 10:31:54

+0

@Aviv Cohn它取決於上下文。 – 2014-10-04 10:33:32

4
Thing thing; 

是缺省初始化。如果Thing是一個類類型,它將調用默認構造函數Thing,就是這樣。

Thing thing = Thing(); 

值初始化了一個臨時Thing然後拷貝/移動該臨時成thing。在實踐中,編譯器將會避免複製/移動,這實際上是一個值初始化,但這仍然需要複製/移動構造函數可用。需要使用= Thing();語法來獲取值初始化語義,因爲Thing thing();是令人煩惱的解析。 *

值初始化和缺省初始化之間的區別是,在某些情況下(具體例depend on the version of the standard,但非聯合類型沒有用戶提供的構造,和非類非陣列類型,以及這些類型的數組在所有版本中都有資格),則在調用默認構造函數之前,值初始化將首先進行初始化。

如果Thing可以是非類(例如,在一個模板中),或者是一個類型,它將獲得零初始化處理(例如POD類),並且您希望它有明確的價值觀。

*Thing thing{};在初始化語義上與C++ 14中的初始化語義有細微的差別。

+1

謝謝。兩個問題:1-一般來說,我應該使用「Thing t;'? 2-在哪些情況下我應該比另一個更喜歡? – 2014-10-04 10:33:17

+0

@AvivCohn我會使用第一個,除非你有理由使用第二個,當'Thing'沒有用戶提供的構造函數並且你希望它的成員具有明確定義的值時使用第二個。 – 2014-10-04 10:38:45

+0

TC的建議是你應該很少做的事情,如果有的話。它讓脆弱的代碼依靠用戶指定對象是初始化還是包含未初始化的值。如果對象應該總是表示某種狀態,那麼它應該有一個構造函數來初始化它的所有成員。 – 2014-10-04 10:41:38

3

記號

Thing thing = Thing(); 

它做了拷貝初始化,可以在C++ 03模板代碼可以用來有效地默認構造一個Thing。事情是,這也適用於內置類型Thing,如int。這個扭曲的符號,因爲寫Thing thing();只是聲明一個函數(一個特例「最令人頭痛的解析」)。

在C++ 11可以代替寫

Thing thing{}; 

在C++ 03的另一種技術是包裹Thingstruct,像這樣:

struct Initialized_thing 
{ 
    Thing thing; 
    Initialized_thing(): thing() {} 
}; 
0

正如其他人寫語法

Thing obj; 

default-initialize您的對象,而語法

Thing obj = Thing(); 

value-initialize您的對象。

第二語法會導致參與更多的東西:

  • 一個移動/拷貝構造函數應該可以訪問
  • 臨時的值初始化
  • 複製省略發生

它們通常用於不同的目的,雖然第一個是最常用於初始化對象的,但後者在值初始化意義上是不同的。

建議閱讀的文檔一個簡單的例子來顯示的差異值和缺省初始化,之間的差異反正如下:

class Thing { 
    public: 

    int data; 

    Thing() { 
     cout << "default ctor" << endl; 
    } 

    Thing(const Thing&) { 
     cout << "copy ctor" << endl; 
    } 

    const Thing& operator=(const Thing&) { 
     cout << "operator=" << endl; 
     return *this; 
    } 
}; 

struct Thingy { 
    int data; 
}; 

int main() { 
    cout << is_pod<Thing>::value << endl; // Thing is NOT pod 

    Thing thing; // Calls default constructor 
    cout << thing.data << endl; // Garbage 

    Thing thing2 = Thing(); // Copy elision is able to optimize this (standard-defined 12.8/31). Anyway a copy/move constructor must be accessible 
    cout << thing2.data << endl; // Garbage 

    // ----------------------------------------------------- 

    cout << is_pod<Thingy>::value << endl; // Thingy IS pod 

    Thingy thingy1; 
    cout << thingy1.data << endl; // garbage 

    Thingy thingy2 = Thingy(); 
    cout << thingy2.data << endl; // zero-initialized! 
} 

上面的代碼將打印

0 // Not a POD 
default ctor 
-1326900592 // garbage 
default ctor 
-1326900592 // garbage 
// --------------------------- 
1 // POD 
-1326900592 // garbage 
0   // zero-initialized 
相關問題