2017-01-27 76 views
3

我有一個叫做Thing的對象,它的構造函數接受一個int值。構造函數調用的C++風格

此代碼按預期工作:

Thing thing(5);

然而,意外我寫了下面:

Thing thing = Thing(5); // note: no 'new'

,並得到了錯誤no matching constructor for initialization of 'Thing'。後面的代碼的實際含義是什麼?我知道這是什麼意思,如果我扔了new在那裏,但沒有新的,這是什麼意思?

+0

如何發生的?我沒有在任何地方使用「顯式」 –

+0

@WhiZTiM'explicit'會阻止調用'Thing thing = 5'。 – rom1v

+3

顯示「Thing」的整個類定義,或至少全部的構造函數。 –

回答

9

Thing thing(5);direct initliazation,thing由相應構造函數(即Thing::Thing(int))直接構建。

Thing thing = Thing(5);copy initialization,這與直接初始化不完全相同。但是對於這種情況,從C++ 17開始,它將直接調用Thing::Thing(int)來構造對象,然後它在這裏與直接初始化具有相同的效果。

首先,如果T是一個類類型和初始值設定爲prvalue表達式,其CV-非限定類型是相同的類T,初始化表達本身,而該臨時從它物化,用於初始化目標對象:看到copy elision

C++ 17之前,第二情況下(即拷貝初始化)需要複製/移動的構造可訪問和非顯式;如果是這種情況,並且您使用的編譯器不支持C++ 17,則會導致錯誤。

如果T是一個類類型和other類型的CV-不合格版本是T或從T派生的類,的T非顯式的構造進行檢查和最佳匹配是由過載分辨率來選擇。然後調用構造函數來初始化該對象。

請注意,從C++ 17開始,代碼會很好地編譯。根據copy elision的規則,複製/移動構造函數不需要可訪問,對於這種情況,explicit

在下列情況下,需要編譯器省略 的複印通和類的構造函數MOVE-對象即使複製/移動 構造函數和析構函數具有可觀察到的副作用:

  • 在初始化過程中,如果初始化表達式是一個prvalue,並且源類型的cv不合格版本與目標類的 類相同,則初始化表達式用於初始化目標對象 :

    T x = T(T(T())); // only one call to default constructor of T, to initialize x 
    
+0

IMO你說的是'事物= 5',而不是'事物=東西(5)'。在後者中,一旦定義了一個拷貝構造函數(但是這個拷貝構造函數不能是'explicit'),構造函數'Thing(int)''explicit'就可以了。 – rom1v

10
Thing thing = Thing(5); 

要求(非explicit)複印件(或移動)-constructor被定義爲:

Thing(const Thing &); 

(即使它不是所謂優化的原因)。

+0

我明白了,所以公式就是在製作一件「事」,然後複製它(而不是毫無意義)。 –

+0

因爲'Thing thing(5);'起作用,所以至少有一個構造函數'Thing(int)'('''explicit'''或'not'),所以你不能在沒有看到類構造函數/成員 – P0W

+2

@ P0W的情況下得出結論。如果'Thing thing = Thing(5)'不起作用,IMO可以斷定複製(/ move) - 構造器丟失。你能提供一個反例嗎? – rom1v