什么时候C ++ 11编译器使RVO和NRVO优于移动语义和const引用绑定? [英] When will a C++11 compiler make RVO and NRVO outperform move semantics and const reference binding?

查看:106
本文介绍了什么时候C ++ 11编译器使RVO和NRVO优于移动语义和const引用绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑如下情况:当启用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 for report1 to use the move constructor triples the instruction count.
  • As noted by James McNellis in his answer below, report2 and report3 does indeed generate identical assembly with 3 times fewer instructions than explicitly calling std::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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆