2017-06-04 220 views
2

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)?

+0

没有关系,反正复制elsiion。 –

回答

2

在何种情况下,(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; 
3

哪一个更好是意见问题。我不会权衡,这不是什么意思。

每个支持C++ 11的现代编译器都会忽略这种移动,除非您传递显式编译器标志以避免不必要的东西。

在C++ 17中,没有移动到elide; thing{}是一个prvalue,而prvalues不是C++ 17中的对象,而是创建对象的指令(可以实例化一个匿名临时对象,但在本例中不是)。

auto x =prvalue;语句会导致使用的prvalue用以建构x