[英]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;
,它只是直接調用運算符, rhs
為y
。 現在考慮一下:
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.