【问题标题】:Why does auto return type lose move semantics in this example?为什么在这个例子中自动返回类型会丢失移动语义?
【发布时间】:2018-02-12 12:42:54
【问题描述】:

我在看video,Nicolai 说这个例子中自动丢失了移动语义:

template<typename Callable, typename... Args>
auto call(Callable&& op, Args&&... args) {
return std::invoke(std::forward<Callable>(op), std::forward<Args>(args)...);
}

我想知道:

  1. 为什么会这样?

  2. guaranteed RVO 是否启动 这个例子?如果是这样,担心搬家有什么意义?

【问题讨论】:

  • 我认为这段代码的问题是,如果 callable 返回一个引用 call 将返回一个从该引用构造的对象。所以使用auto 来声明一个返回类型将使它“不那么完美”向前。视频建议改用decltype(auto)

标签: c++ templates auto c++17


【解决方案1】:

我认为 Nicolai 可以说得更好一些。

当您通过auto 返回时,您的函数会返回一个(将推导出其类型)。如果std::invoke 返回一个纯右值或一个xvalue,那么当然会相应地构造call 的结果(如果可能,通过移动)。从这个意义上说,我们不会“失去移动语义”。

但是当我们按值返回时,需要创建那个值对象。它可以通过移动创建,在某些情况下(which aren't present here)可以省略,但必须创建。保证复制省略不允许我们逃避创建这个对象。

如果 std::invoke 给我们返回一个 xvalue(对某物的右值引用),那可能会非常浪费。为什么要构造一个对象来返回它?

这就是为什么一两张幻灯片后他说我们应该在decltype(auto) 之前返回。然后,扣除规则将保留对std::invoke的调用的值类别:

  1. 如果它返回一个值,我们的情况不会更糟。我们自己的call 将返回一个值(它可以通过移动std::invoke 的返回值来创建)。

  2. 如果std::invoke 返回左值(X&amp;) 或xvalue(X&amp;&amp;),将按原样返回,而无需通过复制或移动创建另一个对象。

    李>

【讨论】:

  • 啊,所以他说的是自动强制用于在返回值之前将可能是 op(args...) 的结果的引用具体化为值的事实。 :) tnx
猜你喜欢
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 2021-10-23
  • 2014-12-29
  • 1970-01-01
相关资源
最近更新 更多