让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)?
答案 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;