为什么 auto return 类型在此示例中丢失了移动语义?
Why does auto return type lose move semantics in this example?
我在看 video Nicolai 说 auto 在这个例子中失去了移动语义:
template<typename Callable, typename... Args>
auto call(Callable&& op, Args&&... args) {
return std::invoke(std::forward<Callable>(op), std::forward<Args>(args)...);
}
我在想:
为什么会这样?
guaranteed RVO 是否启动
这个例子?如果是这样,担心搬家有什么意义?
我认为 Nicolai 可以将其表述得更好一些。
当您通过 auto
return 时,您的函数 return 是一个 值 (将推导其类型)。如果 std::invoke
return 是纯右值或 x 值,那么 call
的结果当然会相应地构造(如果可能,通过移动)。我们不 "lose move semantics" 从这个意义上说。
但是当我们return按值时,需要创建那个值对象。它可以通过移动创建,并且在某些情况下(which aren't present here)可以省略,但必须创建。有保证的复制省略不允许我们逃避创建这个对象。
如果 std::invoke
给我们返回一个 xvalue(对某物的右值引用),那将是非常浪费的。为什么要构造一个对象来return呢?
这就是为什么一两张幻灯片后他说我们应该 return 到 decltype(auto)
。扣除规则将保留调用 std::invoke
:
的值类别
如果它 return 是一个值,我们的情况不会更糟。我们自己的 call
将 return 一个值(它可以通过移动 std::invoke
的 return 值来创建)。
如果 std::invoke
return 是一个左值 (X&
) 或一个 x 值 (X&&
),那将是 return按原样编辑,无需通过复制或移动创建另一个对象。
我在看 video Nicolai 说 auto 在这个例子中失去了移动语义:
template<typename Callable, typename... Args>
auto call(Callable&& op, Args&&... args) {
return std::invoke(std::forward<Callable>(op), std::forward<Args>(args)...);
}
我在想:
为什么会这样?
guaranteed RVO 是否启动 这个例子?如果是这样,担心搬家有什么意义?
我认为 Nicolai 可以将其表述得更好一些。
当您通过 auto
return 时,您的函数 return 是一个 值 (将推导其类型)。如果 std::invoke
return 是纯右值或 x 值,那么 call
的结果当然会相应地构造(如果可能,通过移动)。我们不 "lose move semantics" 从这个意义上说。
但是当我们return按值时,需要创建那个值对象。它可以通过移动创建,并且在某些情况下(which aren't present here)可以省略,但必须创建。有保证的复制省略不允许我们逃避创建这个对象。
如果 std::invoke
给我们返回一个 xvalue(对某物的右值引用),那将是非常浪费的。为什么要构造一个对象来return呢?
这就是为什么一两张幻灯片后他说我们应该 return 到 decltype(auto)
。扣除规则将保留调用 std::invoke
:
如果它 return 是一个值,我们的情况不会更糟。我们自己的
call
将 return 一个值(它可以通过移动std::invoke
的 return 值来创建)。如果
std::invoke
return 是一个左值 (X&
) 或一个 x 值 (X&&
),那将是 return按原样编辑,无需通过复制或移动创建另一个对象。