c++ - C++11 编译器何时会使 RVO 和 NRVO 优于 move 语义和 const 引用绑定(bind)?

标签 c++ optimization reference c++11 move-semantics

考虑从函数返回启用 move 语义的“完整”对象的情况,如 std::basic_string<> :

std::wstring build_report() const
{
    std::wstring report;
    ...

    return report;
}

那么,我是否真的可以做出“最佳”选择,是否将返回的字符串与 move 语义一起使用,如

const std::wstring report(std::move(build_report()));

或者如果我应该依靠 (N)RVO 来发生

const std::wstring report(build_report());

或什至将 const 引用绑定(bind)到临时用

const std::wstring& report(build_report());

有什么方案可以确定性地选择这些选项(如果有的话)?

编辑 1: 注意 std::wstring 的用法以上只是启用 move 语义的类型的示例。它也可以换成你的 arbitrary_large_structure . :-)

编辑 2:我在 VS 2010 中运行速度优化的发布版本时检查了生成的程序集:

std::wstring build_report(const std::wstring& title, const std::wstring& content)
{
    std::wstring report;
    report.append(title);
    report.append(content);

    return report;
}

const std::wstring title1(L"title1");
const std::wstring content1(L"content1");

const std::wstring title2(L"title2");
const std::wstring content2(L"content2");

const std::wstring title3(L"title3");
const std::wstring content3(L"content3");

int _tmain(int argc, _TCHAR* argv[])
{
    const std::wstring  report1(std::move(build_report(title1, content1)));
    const std::wstring  report2(build_report(title2, content2));
    const std::wstring& report3(build_report(title3, content3));

    ...

    return 0;
}

两个最有趣的结果:

  • 显式调用 std::move对于 report1使用 move 构造函数三倍指令计数。
  • 正如 James McNellis 在 his answer below 中所述, report2report3确实生成相同的程序集,指令比显式调用 std::move 少 3 倍.

最佳答案

std::move(build_report()) 完全没有必要:build_report() 已经是一个右值表达式(它是一个返回对象的函数调用按值),因此如果 std::wstring 有一个 move 构造函数(确实如此),则将使用它。

另外,当你返回一个局部变量时,如果它是具有 move 构造函数的类型,它会被 move ,所以不会复制,句号。

report 声明为对象或常量引用之间不应有任何功能差异;在这两种情况下,您最终都会得到一个对象(可以将 report 引用绑定(bind)到的命名 report 对象或未命名对象)。

关于c++ - C++11 编译器何时会使 RVO 和 NRVO 优于 move 语义和 const 引用绑定(bind)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6531700/

相关文章:

c++ - char[] 到十六进制字符串练习

visual-studio-2008 - 将非 GAC 引用添加到项目

c++ - 访问 DLL 中的重载函数

c++ - 使用高斯消元法计算矩阵的逆时非常不准确

c++ - 使用类模板需要数组的模板参数列表

C++ 为什么在定义重载和引用函数时每个函数都应该有一个引用限定符

c++ - 按值或引用传递标量类型 : does it matter?

c++ - cout 在 vector 迭代器 C++ 中似乎无法正常工作

Python 数据结构开销/性能

android - 如何提高 Android 应用程序的整体性能?