3 回答

TA貢獻2036條經(jīng)驗 獲得超8個贊
C ++ 17更新
在C ++ 17中,A_factory_func()
從創(chuàng)建臨時對象(C ++ <= 14)變?yōu)閮H指定此表達式初始化為(松散地說)在C ++ 17中的任何對象的初始化的含義。這些對象(稱為“結果對象”)是由聲明(如a1
)創(chuàng)建的變量,在初始化最終被丟棄時創(chuàng)建的人工對象,或者如果引用綁定需要對象(例如,在A_factory_func();
。最后一種情況下,一個對象是人工創(chuàng)建的,稱為“臨時實現(xiàn)”,因為A_factory_func()
沒有一個變量或引用,否則將需要一個對象存在)。
如在我們的情況下的例子,在的情況下,a1
和a2
特別規(guī)則說,在這樣的聲明,相同的類型的一個prvalue初始化的結果對象a1
是可變的a1
,因此A_factory_func()
直接初始化對象a1
。任何中間函數(shù)式轉換都不會產(chǎn)生任何影響,因為A_factory_func(another-prvalue)
只是“傳遞”外部prvalue的結果對象也是內(nèi)部prvalue的結果對象。
A a1 = A_factory_func();A a2(A_factory_func());
取決于什么類型A_factory_func()
返回。我假設它返回一個A
- 然后它正在做同樣的事情 - 除了復制構造函數(shù)是顯式的,然后第一個將失敗。閱讀8.6 / 14
double b1 = 0.5;double b2(0.5);
這樣做是因為它是內(nèi)置類型(這意味著這里不是類類型)。閱讀8.6 / 14。
A c1;A c2 = A();A c3(A());
這不是一樣的。第一個默認初始化if A
是非POD,并且不對POD進行任何初始化(Read 8.6 / 9)。第二個副本初始化:值初始化臨時值,然后將該值復制到c2
(讀取5.2.3 / 2和8.6 / 14)。這當然需要一個非顯式的復制構造函數(shù)(Read 8.6 / 14和12.3.1 / 3和13.3.1.3/1)。第三個為函數(shù)創(chuàng)建一個函數(shù)聲明,該函數(shù)c3
返回一個A
并且函數(shù)指針返回一個返回a的函數(shù)A
(Read 8.2)。
深入研究初始化直接和復制初始化
雖然它們看起來相同并且應該做同樣的事情,但在某些情況下這兩種形式卻截然不同。兩種形式的初始化是直接和復制初始化:
T t(x);T t = x;
我們可以將行為歸因于每個行為:
直接初始化的行為類似于對重載函數(shù)的函數(shù)調(diào)用:在這種情況下,函數(shù)是
T
(包括explicit
一些)的構造函數(shù),參數(shù)是x
。重載解析將找到最佳匹配構造函數(shù),并在需要時將執(zhí)行任何隱式轉換。復制初始化構造一個隱式轉換序列:它嘗試轉換
x
為類型的對象T
。(然后它可以將該對象復制到to-initialized對象,因此也需要復制構造函數(shù) - 但這在下面并不重要)
如您所見,復制初始化在某種程度上是關于可能的隱式轉換的直接初始化的一部分:雖然直接初始化具有可用于調(diào)用的所有構造函數(shù),并且此外可以進行任何隱式轉換,它需要匹配參數(shù)類型,復制初始化可以設置一個隱式轉換序列。
我努力嘗試并獲得以下代碼,為每個表單輸出不同的文本,而不使用“明顯的”通過explicit
構造函數(shù)。
#include <iostream>struct B;struct A { operator B();};struct B { B() { } B(A const&) { std::cout << "<direct> "; }};A::operator B() { std::cout << "<copy> "; return B(); }int main() { A a; B b1(a); // 1) B b2 = a; // 2)}// output: <direct> <copy>
它是如何工作的,為什么輸出結果呢?
直接初始化
它首先對轉換一無所知。它只會嘗試調(diào)用構造函數(shù)。在這種情況下,以下構造函數(shù)可用且完全匹配:
B(A const&)
調(diào)用該構造函數(shù)不需要轉換,更不用說用戶定義的轉換了(請注意,此處也不會發(fā)生const限定轉換)。所以直接初始化會調(diào)用它。
復制初始化
如上所述,復制初始化將在
a
未輸入B
或從中導出時構建轉換序列(這里顯然是這種情況)。因此,它將尋找進行轉換的方法,并將找到以下候選人B(A const&)operator B(A&);
注意我是如何重寫轉換函數(shù)的:參數(shù)類型反映了
this
指針的類型,在非const成員函數(shù)中它是非const的?,F(xiàn)在,我們將這些候選人x
稱為爭論。獲勝者是轉換函數(shù):因為如果我們有兩個候選函數(shù)都接受對相同類型的引用,則較少的const版本獲勝(順便說一下,這也是非const成員函數(shù)調(diào)用非機制的機制) -const對象)。請注意,如果我們將轉換函數(shù)更改為const成員函數(shù),則轉換是不明確的(因為它們都具有
A const&
當時的參數(shù)類型):Comeau編譯器正確拒絕它,但GCC在非迂腐模式下接受它。但是切換到-pedantic
它也會輸出正確的模糊警告。
我希望這有助于使這兩種形式的區(qū)別更加清晰!

TA貢獻1848條經(jīng)驗 獲得超10個贊
分配與初始化不同。
以下兩行都進行了初始化。完成一個構造函數(shù)調(diào)用:
A a1 = A_factory_func(); // calls copy constructorA a1(A_factory_func()); // calls copy constructor
但它并不等同于:
A a1; // calls default constructora1 = A_factory_func(); // (assignment) calls operator =
我目前沒有文字來證明這一點,但實驗起來很容易:
#include <iostream>using namespace std;class A {public: A() { cout << "default constructor" << endl; } A(const A& x) { cout << "copy constructor" << endl; } const A& operator = (const A& x) { cout << "operator =" << endl; return *this; }};int main() { A a; // default constructor A b(a); // copy constructor A c = a; // copy constructor c = b; // operator = return 0;}

TA貢獻1851條經(jīng)驗 獲得超3個贊
double b1 = 0.5;
是構造函數(shù)的隱式調(diào)用。
double b2(0.5);
是明確的電話。
查看以下代碼以查看差異:
#include <iostream>class sss { public: explicit sss( int ) { std::cout << "int" << std::endl; }; sss( double ) { std::cout << "double" << std::endl; };};int main() { sss ddd( 7 ); // calls int constructor sss xxx = 7; // calls double constructor return 0;}
如果你的類沒有顯式的構造,那么顯式和隱式調(diào)用是相同的。
- 3 回答
- 0 關注
- 736 瀏覽
添加回答
舉報