【问题标题】:Returning std::move(f) in std::for_each在 std::for_each 中返回 std::move(f)
【发布时间】:2013-08-24 12:16:39
【问题描述】:

我正在编写标准 c++ 库的实现以供学习。

C++11 标准规定 for_each 返回 std::move(f)

template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);

Returns: std::move(f).

我认为函数作用域局部变量在返回时是移动构造的。 我应该明确返回move(f) 吗?

【问题讨论】:

  • 在这种情况下,返回std::move(f)几乎等同于返回f。 C++11 禁止函数参数的返回值优化(但仍允许对它们进行隐式移动)。因此,在我看来,唯一的区别是return f; 会退回到将其视为左值,如果右值会导致重载歧义或找不到构造函数。但是return move(f) 在这种情况下会因格式错误而失败。
  • 例如,对于像 struct Function { Function(Function&amp;); }; 这样定义的 Function,行为会有所不同。此类没有移动构造函数和不接受右值的复制构造函数。因此,move(f) 返回格式错误,而 return f; 格式正确。
  • 但话又说回来,我不确定函数对象的库约束是什么。也许他们需要 Function 从右值复制初始化。据我所知,在这种情况下确实没有区别。
  • 谢谢。 std::for_each 要求 FunctionMoveConstructible 但不是 CopyConstructible,因此返回 move(f) 用于强制 FunctionMoveConstructible。检查不可移动类,如果我返回move(f),则会发生编译错误。

标签: c++ c++11 std move-semantics c++-standard-library


【解决方案1】:

来自 Josuttis 的 C++ 标准库

您不必也不应该 move() 返回值。根据语言规则,标准规定对于以下代码

X foo ()
{
X x;
...

return x;
}

保证以下行为:

• 如果 X 具有可访问的副本或移动构造函数,编译器可能 选择省略副本。这就是所谓的(命名的)返回值 优化 ((N)RVO),甚至在 C++11 之前就已经指定,并且是 大多数编译器都支持。

• 否则,如果 X 具有移动构造函数,则移动 x。

• 否则,如果 X 具有复制构造函数,则复制 x。

• 否则,会发出编译时错误。

来自 §25.2.4 (for_each)

Requires:Function 应满足MoveConstructible 的要求 (表 20)。 [注:功能不必满足要求 CopyConstructible(表 21)。—结束注]

使用std::move(f),您可以保证能够从外部读取变异状态。

【讨论】:

  • 我错过了Function的要求。谢谢。
  • 但是,该问题询问的是函数参数“f”,而标准则给出了一个带有局部变量的示例。 RVO 是否适用于函数参数?
猜你喜欢
  • 2017-10-19
  • 2018-03-21
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 1970-01-01
相关资源
最近更新 更多