默认初始化与默认构造值的复制初始化

时间:2017-06-04 18:06:59

标签: c++ c++11

thing成为默认可构造且可移动构造的类型。考虑以下两个初始化:

thing t1;          // (1)
auto t2 = thing{}; // (2)
  • (1)default-constructs t1

  • (2)default-构造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)时,变量名称会显示在右侧。使用(2)时,无论typename有多长,变量名都是同样明显的。

这是否意味着为了一致性,(2)优于(1)?

2 个答案:

答案 0 :(得分:3)

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

每个支持C ++ 11的现代编译器都会忽略该移动,除非您将显式编译器标志传递给永远不会删除。

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

auto x = prvalue ;语句会导致prvalue指令用于构建x

答案 1 :(得分:2)

  

在哪种情况下,(2)中的举动会被省略?

当编译器选择忽略时。这实际上总是在现代编译器上。但是,C ++ 11(也不是C ++ 14)中没有保证的复制省略。

  

使用(2)将与这些样式一致,而使用(1)则不会。

     

这是否意味着为了一致性,(2)优于(1)?

为了一致性,一致性几乎没有优势。

理解为什么类型在示例中的右侧,以及auto的原因(这意味着)存在是很有用的。类型在右侧,因为模板实例化需要它。仍然一个类型必须在左侧也具有声明的语法。该类型也是右手表达式的返回类型,因此引入auto以允许从该表达式中进行推导。这是有利的,因为我们避免了类型的脆弱重复。

(1)没有重复,因此在引入auto时没有重复数据删除优势。没有右手表达,也没有必要引入一个。 (2)有不必要的额外样板,以及可移动类型的附加要求。

  

此外,当使用带有长类型名称的(1)时,变量名称会显示在右侧。使用(2)时,无论typename有多长,变量名都是同样明显的。

在我看来,这是一个微弱的论点。无论如何,你应该避免使用不必要的长类型名称,但是如果你遇到一个类型名称,你可以简单地将它们放在不同的行中:

thing_with_extra_long_type_name_for_some_reason<omg_it_doesnt_end>
  t1;