提问者:小点点

初始化:括号与等号[重复]


可能的重复:
在C++中,复制初始化和赋值初始化之间是否有区别?

有什么区别

T a(b);

T a = b;

T a = T(b);


共3个答案

匿名用户

T a( b );

是直接初始化,除非它解析为函数声明,在这种情况下它是函数声明。

T a = b;

是复制初始化,这意味着它的工作方式就像在右侧构造了一个临时对象一样,然后从该临时对象复制构造a,或者在C++11和更高版本中,可能从该临时对象移动构造。

编译器可以自由地删除(删除)临时的+复制/移动,但是复制或移动构造函数(无论在逻辑上使用哪一个)必须仍然是可访问的,而不是显式的

例如,在C++03中,您不能复制-初始化std::oStringStream,因为它没有复制构造函数。 在C++11中,如果初始值设定项是临时的,则可以复制-初始化oStringStream,这将导致逻辑移动构造(然而通常会被省略,优化掉)。 例如,此复制初始化声明,

ostringstream s = ostringstream( "blah" );

…不编译为C++03,因为在C++03中,复制初始化调用类的复制构造函数,而它并不存在。 但是,它可以编译为C++11,因为在C++11中,复制初始化调用移动构造函数。 虽然不能直接复制std::oStringStream(为了保持它是一个流的错觉),但是可以移动该std::oStringStream

另一个类似的区别是:在C++03中,只有复制初始化语法支持花括号初始化器,在C++03中,当T是聚合类型(如raw数组)时,可以使用该初始化器。 在C++11中,花括号表示法被扩展和推广为一种统一的初始化语法,因此它也可以用于直接初始化。 因此下面的直接初始化声明,

int v[]{ 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };

…不编译为C++03,但编译为C++11和更高版本。

=复制初始化语法是C的原始初始化语法。

在C++11和更高版本中,由于move语义,它可以用于比C++03更广泛的情况,例如与std::oStringStream一起使用。

匿名用户

T a(b);

调用接受Ba的构造函数。 (如果b类型相同,则调用复制构造函数)。

T a = b;

创建一个T类型的临时对象,由B构造。 然后调用复制构造函数(=在本例和下一例中不是赋值!)。

T a = T(b);

同上! 只是我们显式构造了一个临时对象。

请注意,标准允许在第二种和第三种情况下完全消除临时副本。 另外,如果B不是T类型,那么在第一种情况下,T不必具有复制构造函数。 在第二种和第三种情况下,即使实现可以自由地优化整个事情,它仍然需要一个可访问的复制构造函数。 IIRC标准称之为:复制删除。

匿名用户

它们都是构造函数调用-=符号只是句法上的糖。 具体调用哪些构造函数在一定程度上取决于编译器。