簡體   English   中英

在堆棧上聲明對象的兩種方式之間的區別

[英]Difference between two ways of declaring an object on the stack

假設我沒有在類Beatle指定復制構造函數和operator= ,以下兩個聲明之間有什么區別?

Beatle john(paul);

Beatle john = paul;

編輯:

在對象賦值中,除非另有說明,否則operator =隱式調用復制構造函數?

他們是不同的語法結構。 第一個是直接初始化 ,第二個是復制初始化 它們的行為幾乎相同,只是第二個需要非explicit構造函數。*

兩者都與賦值運算符無關,因為兩行都是初始化

即: const int i = 4; 很好,但是const int i; i = 4; const int i; i = 4; 不是。

*)更准確:如果相關構造函數被聲明為explicit則第二個版本不起作用。 因此,更一般地說,直接初始化為您提供了一個“免費”轉換:

struct Foo { Foo(std::string) {} };

Foo x("abc");  // OK: char(&)[4] -> const char * -> std::string -> Foo
Foo y = "abd"; // Error: no one-step implicit conversion of UDTs

解決編輯問題:要了解賦值運算符,只需將其分解為多個部分即可。 假設Foo有明顯的operator=(const Foo & rhs) 我們可以說x = y; ,它只是直接調用運算符, rhsy 現在考慮一下:

x = "abc";              // error, no one-step implicit conversion
x = std::string("abc"); // fine, uses Foo(std::string), then copy
x = Foo("abc");         // fine, implicit char(&)[4] -> const char* -> std::string, then as above

首先是直接初始化,第二是復制初始化。

直接初始化意味着使用單個(可能是轉換)構造函數初始化對象,並且等效於形式T t(u);

U u;
T t1(u); // calls T::T( U& ) or similar

復制初始化意味着在必要時首次調用用戶定義的轉換后,使用復制構造函數初始化對象,並且等效於T t = u;

T t2 = t1;  // same type: calls T::T( T& ) or similar
T t3 = u;   // different type: calls T::T( T(u) )
            //  or T::T( u.operator T() ) or similar

如果構造函數聲明為explicit則復制初始化不起作用。

參考文獻:
Herb Sutter的GOTW中的這個條目應該是一個很好的閱讀。


要回答您編輯的問題:
=具有不同的含義取決於它的使用方式。

如果在用於同時創建和初始化對象的表達式中使用= ,則=不被視為賦值運算符,而是被視為復制初始化。

如果=正被用於將一個對象分配到另一個時,對象已經創建之后然后它導致調用賦值運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM