【问题标题】:Complete example of (N)RVO(N)RVO 的完整示例
【发布时间】:2012-10-20 09:51:44
【问题描述】:

我一直在阅读有关 (N)RVO 的内容,并且想要一份完整的场景描述。我希望这个问题能帮助其他 C++ 学习者澄清他们的想法。

假设这种情况:

string get_string() {
    string x("racecar");
    //work on x...
    return x;
}

string a( get_string() );
string b = get_string();

请暂时忽略 C++11 移动语义。

  • 如果不执行 (N)RVO,将有多少个构造函数/赋值/析构函数 执行? (请指出它们所指的对象)
  • 如果应用 (N)RVO,会发生什么变化?
  • 最后,假设std::string 支持,C++11 中的情况如何变化 移动语义。

【问题讨论】:

    标签: c++ move-semantics nrvo


    【解决方案1】:

    1) 在get_string 内部,将使用带有const char* 的构造函数构造一个字符串对象(x)。

    2) 当函数返回时,内部构造的字符串会被复制构造到调用者空间中的一个临时字符串对象中。

    3) 临时将被复制构造到a

    4) 见 1

    5) 见 2

    6) 见 3,但副本将转到 b

    使用 RVO,2 和 5 可以通过在函数内部通过不可见的引用构造临时来消除。通过进一步的复制省略(不是 RVO),可以消除 3 和 6。所以这给我们留下了 2 个构造,都使用 const char* 构造函数。

    使用 C++11 移动语义,如果编译器足够好来完成所有复制省略,情况根本不会改变。如果没有复制省略,那么 2、3、5 和 6 仍然存在,但变成移动而不是复制。然而,与复制省略不同,这些移动不是可选的优化。一个符合标准的编译器必须执行它们,假设它还没有执行复制省略。

    【讨论】:

    • RVO 只是消除了副本 (2) 和 (5)。副本 (3) 和 (6) 可以通过与 (n) RVO 应用无关的临时性的正常省略来消除。
    • @CharlesBailey:你是对的。我倾向于将 RVO 与一般复制省略混为一谈,因为我同时了解了这两者。
    • 这几乎是我需要知道的,谢谢 :) 您是否有任何指向您(可能)在您的回答中未提及的主题的链接?
    猜你喜欢
    • 2015-05-17
    • 2023-03-22
    • 2014-03-13
    • 2022-10-15
    • 1970-01-01
    • 2021-04-14
    • 2011-05-03
    • 2017-08-18
    • 2012-10-12
    相关资源
    最近更新 更多