将参数的省略复制为返回值

dal*_*lle 2 c++ copy-elision c++17

  1. 鉴于以下; C++17 会保证复制省略吗?
template <typename Widget>
Widget frobnicate(Widget w) {
  // optionally mutate w in some way
  return w;
}
Run Code Online (Sandbox Code Playgroud)
  1. 如果Widget实现移动构造函数,答案是否会改变?

  2. 我应该搬家回来吗?例如,在这种情况下:

return std::move(w);
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 7

  1. 不可以。我们不能保证从函数参数中删除副本。如果您从实现的角度考虑这一点 - 您的参数w必须存在于某个寄存器或地址中,因此不能首先将其构造到返回槽中。

  2. 鉴于(1),有点没有实际意义。

  3. 你永远不应该†‡写,return std::move(w);因为这实际上会抑制快乐情况下的复制省略:

    Widget frobnicate() {
        Widget w;
        return std::move(w); // oops
    }
    
    Run Code Online (Sandbox Code Playgroud)

除了在 C++17 中实际上有一些不幸的地方您实际上需要编写,std::move因为有些地方不会自动为您移动对象。有关几个示例,请参见P0527P1155(OP 情况 - 返回函数参数 - 不是其中之一;即使在 C++17 中,也会隐式地移出该参数)。C++20也会隐式地摆脱所有这些情况,所以你真的不应该return std::move(w);

当然,除非w不是具有自动存储期的函数参数或局部变量。那么语言中的任何内容都不能安全地假设它可以代表您移动它,因此您必须明确地这样做。