可能重复:
Is there a difference in C++ between copy initialization and assignment initialization?
之间有什么区别
T a(b);
和
T a = b;
和
T a = T(b);
答案 0 :(得分:26)
T a( b );
是直接初始化,除非它作为函数声明解析,在这种情况下它是一个函数声明。
T a = b;
是复制初始化,这意味着它就好像在右侧构造了一个临时对象,然后a
被复制构造,或者在C ++ 11中然后,可能从那个临时的移动构建。
编译器可以随时删除(删除)临时+复制/移动,但复制或移动构造函数(无论在逻辑上使用哪个)必须仍然可以访问,而不是explicit
。
例如,在C ++ 03中,您无法复制初始化std::ostringstream
,因为它没有复制构造函数。在C ++ 11中,如果初始化程序是临时的,则可以复制初始化ostringstream
,然后导致逻辑移动构造(但通常会被省略,优化掉)。例如,这个拷贝初始化声明,
ostringstream s = ostringstream( "blah" );
...不编译为C ++ 03,因为在C ++ 03中,复制初始化调用了类的复制构造函数,该构造函数不存在。然而,它确实编译为C ++ 11,因为在C ++ 11中,复制初始化调用移动构造函数。虽然(为了保持其作为流的假象)无法直接复制std::ostringstream
,但可以移动。
另一个这样的区别:在C ++ 03中,只有复制初始化语法支持花括号初始化程序,在C ++ 03中,当T
是聚合类型时,可以使用它原始数组。在C ++ 11中,花括号表示法已经扩展并概括为统一初始化语法,因此它也可以用于直接初始化。以下是直接初始化声明,
int v[]{ 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };
...不编译为C ++ 03,但编译为C ++ 11及更高版本。
=
复制初始化语法是C的原始初始化语法。
在C ++ 11及更高版本中,由于移动语义,它可以在比C ++ 03更广泛的情况下使用,例如使用std::ostringstream
。
答案 1 :(得分:19)
T a(b);
调用接受a
的{{1}}构造函数。 (如果b
属于同一类型,则调用复制构造函数。)
b
创建T a = b;
类型的临时对象,由T
构造。然后调用复制构造函数(在这种情况下,b
不是赋值,下一个案例!)。
=
同上!除了我们明确构造了一个临时对象。
请注意,该标准允许在第二种和第三种情况下完全取消临时副本。此外,如果T a = T(b);
不是b
类型,那么在第一种情况下T
不必具有复制构造函数。在第二和第三种情况下,即使实现可以自由地优化整个事物,它仍然需要一个可访问的复制构造函数。 IIRC标准称之为: copy elision 。
答案 2 :(得分:-2)
它们都是构造函数调用 - =符号只是语法糖。究竟哪些构造函数被调用在某种程度上直到编译器。
答案 3 :(得分:-3)
=运算符将调用默认的复制构造函数,除非=运算符被重载我相信......这会产生一个浅的副本;将相同的成员值分配给第一个对象作为右侧操作符