默认初始化与默认构建值的初始化初始化
设thing
为默认构造和移动构造类型。考虑以下两个初始化:默认初始化与默认构建值的初始化初始化
thing t1; // (1)
auto t2 = thing{}; // (2)
(1)默认构造
t1
。(2)默认构建
thing
类型的临时表并将其移至t2
。
在何种情况下,(2)中的移动将被消除?
在现代风格的C++初始化中,类型通常根本不出现或出现在右侧。例如:
auto copy = vec; // Type doesn't appear
auto p_derived = std::make_unique<derived>(); // Type appears naturally on the right
// Putting the type on the right here makes it explicit that the upcast is intended
auto p_base = std::unique_ptr<base>{ std::make_unique<derived>() };
使用(2)将与这些样式一致,而使用(1)则不会。
另外,当使用(1)long typename时,变量名称显示在右侧。当使用(2)时,无论类型名称的长度如何,变量名称同样适用。
这是否意味着(2)为了一致性而优于(1)?
在何种情况下,(2)中的移动将被消除?
当编译器选择退出。这实际上总是在现代编译器上。但是,在C++ 11(也不是C++ 14)中没有保证副本的省略。
使用(2)将与这些样式一致,而使用(1)则不会。
这是否意味着(2)为了一致性而优于(1)?
为了一致性的缘故,一致性几乎没有什么优势。
理解为什么类型在您的示例中是正确的,以及为什么(这个意思是)auto
存在是有用的。该类型在右侧,因为它在模板实例化中需要。还有一种类型也必须在左侧也有声明的语法。该类型也是右手表达式的返回类型,因此引入了auto
以允许从该表达式中扣除。这是有利的,因为我们避免了类型的脆弱重复。
(1)没有重复,因此在引入auto
时没有重复删除优势。没有右手表达,也没有必要介绍一个。 (2)具有不必要的额外样板,并且可移动类型的附加要求。
此外,当使用(1)与long typename时,变量名称显示在右侧。当使用(2)时,无论类型名称的长度如何,变量名称同样适用。
在我看来,这是一个弱的论点。你应该避免不必要的长typenames反正,但如果你坚持一个,你可以简单地将它们放在不同的行:
thing_with_extra_long_type_name_for_some_reason<omg_it_doesnt_end>
t1;
哪一个更好是意见问题。我不会权衡,这不是什么意思。
每个支持C++ 11的现代编译器都会忽略这种移动,除非您传递显式编译器标志以避免不必要的东西。
在C++ 17中,没有移动到elide; thing{}
是一个prvalue,而prvalues不是C++ 17中的对象,而是创建对象的指令(可以实例化一个匿名临时对象,但在本例中不是)。
的auto x =
prvalue;
语句会导致使用的prvalue用以建构x
。
没有关系,反正复制elsiion。 –