什么时候C ++ 11编译器使RVO和NRVO优于移动语义和const引用绑定? [英] When will a C++11 compiler make RVO and NRVO outperform move semantics and const reference binding?
问题描述
考虑如下情况:当启用move语义的整个对象从函数返回时,如 std :: basic_string<>
:
Consider the case when "whole" objects with move semantics enabled are returned from functions, as with std::basic_string<>
:
std::wstring build_report() const
{
std::wstring report;
...
return report;
}
然后我可以真正地期望做出最好的 (std :: move(build_report()))中返回的带有移动语义的字符串,如
Can I then realistically be expected to make the "best" choice whether to use the returned string with move semantics, as in
const std::wstring report(std::move(build_report()));
或者如果我应该依靠RVO来执行
or if I should rely on (N)RVO to take place with
const std::wstring report(build_report());
或者甚至使用
const std::wstring& report(build_report());
如果有什么方案可以确定性地选择这些选项? strong>
What scheme is there to make a deterministic choice of these options, if any?
编辑1:请注意,上面的 std :: wstring
只是移动语义启用类型的一个示例。它也可以换成你的 arbitrary_large_structure
。 : - )
EDIT 1: Note that the usage of std::wstring
above is just an example of a move semantics enabled type. It just as well be swapped for your arbitrary_large_structure
. :-)
编辑2:在VS 2010中运行以速度优化的发布版本时,我检查了生成的程序集: p>
EDIT 2: I checked the generated assembly when running a speed-optmized release build in VS 2010 of the following:
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
-a-c0x-compiler-make-rvo-and-nrvo-outperform-move-semantics-and-const / 6531758#6531758#6531758>他的回答如下,report2
和report3
确实生成相同的程序集,其指令比显式调用std :: move
li>
- Explicitly calling
std::move
forreport1
to use the move constructor triples the instruction count. - As noted by James McNellis in his answer below,
report2
andreport3
does indeed generate identical assembly with 3 times fewer instructions than explicitly callingstd::move
.
推荐答案
std :: move(build_report())
完全不必要: build_report()
已经是一个右值表达式(它是一个按值返回对象的函数的调用),因此 std :: wstring
move构造函数将被使用,如果它有一个(它的)。
std::move(build_report())
is wholly unnecessary: build_report()
is already an rvalue expression (it is a call of a function that returns an object by value), so the std::wstring
move constructor will be used if it has one (it does).
,如果它是一个具有移动构造函数的类型,则它会被移动,因此不会产生副本。
Plus, when you return a local variable, it gets moved if it is of a type that has a move constructor, so no copies will be made, period.
声明之间不应有任何功能差异 report
作为对象或const引用;在这两种情况下,你最终得到一个对象(或者 report
对象或者一个未命名的对象,报告
可以绑定)。
There shouldn't be any functional difference between declaring report
as an object or as a const-reference; in both cases you end up with an object (either the named report
object or an unnamed object to which the report
reference can be bound).
这篇关于什么时候C ++ 11编译器使RVO和NRVO优于移动语义和const引用绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!