假设我没有在类operator=
中指定复制构造函数和Beatle
,以下两个声明之间有什么区别?
Beatle john(paul);
和
Beatle john = paul;
编辑:
在对象赋值中,除非另有说明,否则运算符=
会隐式调用复制构造函数?
答案 0 :(得分:7)
他们是不同的语法结构。第一个是直接初始化,第二个是复制初始化。它们的行为几乎相同,只是第二个需要非explicit
构造函数。*
两者都与赋值运算符无关,因为这两行都是初始化。
即便:const int 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
答案 1 :(得分:2)
首先是直接初始化&第二是复制初始化。
直接初始化表示使用单个(可能是转换)构造函数初始化对象,并且等同于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中的 This 条目应该是一个很好的阅读。
回答您编辑过的问题:
=
具有不同的含义,具体取决于它的使用方式。
如果在同时创建和初始化对象的表达式中使用=
,则=
不会被视为分配运算符而是被视为复制初始化。
如果=
用于将一个对象分配给另一个对象,在之后创建了该对象,则会导致对Assignment Operator的调用。