【发布时间】:2011-09-25 18:41:18
【问题描述】:
考虑从函数返回启用了移动语义的“完整”对象的情况,如std::basic_string<>:
std::wstring build_report() const
{
std::wstring report;
...
return report;
}
那么,我是否真的可以做出“最佳”选择,是否将返回的字符串与移动语义一起使用,如
const std::wstring report(std::move(build_report()));
或者如果我应该依靠 (N)RVO 来发生
const std::wstring report(build_report());
或什至将 const 引用绑定到临时用
const std::wstring& report(build_report());
有什么方案可以确定性地选择这些选项(如果有的话)?
编辑 1: 请注意,上面使用的 std::wstring 只是启用移动语义的类型的示例。它也可以换成你的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;
}
两个最有趣的结果:
- 为
report1显式调用std::move以使用移动构造函数三倍指令计数。 - 正如 James McNellis 在 his answer below、
report2和report3中所指出的,确实生成相同的程序集,其指令比显式调用std::move少 3 倍。
【问题讨论】:
-
我认为对
move的调用没有被内联和消除,这真的很奇怪。 -
@James:是的,特别是考虑到 Kerrek SB 的评论,即 STL 说 RVO 发生在在其他任何事情之前。 (stackoverflow.com/questions/6531700/…) 你不是在STL附近,所以你可以走过去问他吗? ;-)
-
@Howard:虽然你对这个问题的回答很好,但我认为这个问题解决了更深层次的问题。
-
我确实在他工作的大楼里度过了相当多的时间,是的 :-) 不过,我还没有真正见过 STL 先生本人。不过,我会跟进他们为什么
std::move没有在这里内联;我真的觉得这很令人费解。我下周末都在休假,所以我要过几周才能回复你。
标签: c++ optimization reference c++11 move-semantics