【问题标题】:How to avoid the "pessimizing-move" warning of NRVO?如何避免NRVO的“悲观行动”警告?
【发布时间】:2020-05-28 09:34:15
【问题描述】:
#include <string>

std::string f()
{
    std::string s;
    return std::move(s);
}

int main()
{
    f();
}

g++ -Wall z.cpp 给出警告如下:

z.cpp: In function ‘std::string f()’:
z.cpp:6:21: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
    6 |     return std::move(s);
      |            ~~~~~~~~~^~~
z.cpp:6:21: note: remove ‘std::move’ call

我知道如果我将return std::move(s); 更改为return s;,将避免警告。但是,根据C++ standardNRVO,说在这种情况下,是不能保证的。如果我写return s;,我不确定NRVO是否会被执行。

如何缓解不确定感?

【问题讨论】:

  • 在这种情况下,复制省略怎么办?
  • 本例不保证复制省略。
  • 您可以'return s',让编译器生成列表,然后读取它以查看编译器是否复制省略。如果没有,您可以将函数更改为 'void f(std::string& s)'

标签: c++ performance c++17 standards nrvo


【解决方案1】:

你应该这样做

std::string f()
{
    std::string s;
    return s;
}

如果 NRVO 不适用,移动会自动完成。

return#Automatic_move_from_local_variables_and_parameters

【讨论】:

  • @xmllmx:添加了 cppreference 链接
【解决方案2】:

如何避免NRVO的“悲观行动”警告?

只需删除std::move。它在这里没有做任何有用的事情,但确实可以防止省略移动。

如果我写return s;,我不确定是否会执行NRVO。

如何缓解不确定感?

从不保证 NRVO。为缓解不确定性,您能做的最好的事情就是编译并查看移动是否被忽略。在实践中,只要启用优化,我相信任何现代编译器都会执行此 NRVO。

如果您想确定要避免任何移动,请返回纯右值而不是左值。这保证从 C++17 开始被忽略:

std::string f()
{
    return {};
}

【讨论】:

    猜你喜欢
    • 2016-12-25
    • 2021-02-04
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 2021-09-01
    • 2014-10-23
    相关资源
    最近更新 更多