初始化:括号与等号

时间:2010-12-17 12:42:54

标签: c++ initialization

  

可能重复:
  Is there a difference in C++ between copy initialization and assignment initialization?

之间有什么区别
T a(b);

T a = b;

T a = T(b);

4 个答案:

答案 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)

=运算符将调用默认的复制构造函数,除非=运算符被重载我相信......这会产生一个浅的副本;将相同的成员值分配给第一个对象作为右侧操作符

相关问题