考虑从函数返回启用 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 中所述,
report2
和report3
确实生成相同的程序集,指令比显式调用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/