fre*_*low 35 c++ initialization
可能重复:
复制初始化和赋值初始化之间的C++是否存在差异?
有什么区别
T a(b);
Run Code Online (Sandbox Code Playgroud)
和
T a = b;
Run Code Online (Sandbox Code Playgroud)
和
T a = T(b);
Run Code Online (Sandbox Code Playgroud)
?
Che*_*Alf 28
T a( b );
Run Code Online (Sandbox Code Playgroud)
是直接初始化,除非它作为函数声明解析,在这种情况下它是一个函数声明.
T a = b;
Run Code Online (Sandbox Code Playgroud)
是复制初始化,这意味着它就好像在右侧构造一个临时对象,a然后复制构造,或者在C++ 11及更高版本中,可能从该临时构造移动构造.
只要有可能,编译器就可以自由地删除(删除)临时+复制/移动,但是复制或移动构造函数(无论哪个逻辑上使用)必须仍然可以访问而不是explicit.
例如,在C++ 03中,您无法复制初始化a std::ostringstream,因为它没有复制构造函数.在C++ 11中,ostringstream如果初始化程序是临时的,则可以复制初始化,然后导致逻辑移动构造(但通常会被省略,优化掉).例如,这个复制初始化声明,
ostringstream s = ostringstream( "blah" );
Run Code Online (Sandbox Code Playgroud)
...不编译为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 };
Run Code Online (Sandbox Code Playgroud)
...不编译为C++ 03,但编译为C++ 11及更高版本.
该=副本初始化语法与C的原始初始化语法
在C++ 11及更高版本中,由于移动语义,它可以在比C++ 03更广泛的情况下使用,例如使用std::ostringstream.
Ara*_*raK 19
T a(b);
Run Code Online (Sandbox Code Playgroud)
调用a接受的构造函数b.(如果b是相同类型,则调用复制构造函数).
T a = b;
Run Code Online (Sandbox Code Playgroud)
T创建一个类型的临时对象来构造b.然后调用复制构造函数(=在这种情况下不是赋值,下一个案例!).
T a = T(b);
Run Code Online (Sandbox Code Playgroud)
和上面一样!除了我们显式构造一个临时对象.
请注意,该标准允许在第二种和第三种情况下完全消除临时副本.另外,如果b不是类型T,那么在第一种情况下T不必具有复制构造函数.在第二和第三种情况下,即使实现可以自由地优化整个事物,它仍然需要一个可访问的复制构造函数.IIRC的标准称之为:复制省略.
| 归档时间: |
|
| 查看次数: |
20648 次 |
| 最近记录: |