【问题标题】:NRVO - Is the output of this program well defined?NRVO - 这个程序的输出是否定义良好?
【发布时间】:2014-03-07 13:15:53
【问题描述】:
#include <iostream>
using namespace std;

int gc = 0;
struct A {
    int id;
    A():id(gc++) { cout << "Constructed #" << id << "\n"; }
    A(const A& b):id(gc++) { cout << "Copying from " << b.id << " to " << id << "\n"; }
    ~A() { cout << "Destructed #" << id << "\n"; }
};
A f() {
    A a;
    cout << "Exiting f()" << "\n";
    return a;
}
int main() {
    A b = f();
    cout << "Exiting main()" << "\n";
    return 0;
}

产生的输出(没有优化 (-O0),并使用以下任一编译器:g++ 4.6.3、g++ 4.8.1、clang++ 3.0 在 Ubuntu 上):

Constructed #0
Exiting f()
Exiting main()
Destructed #0

我猜测没有调用复制构造函数(尽管它具有可观察到的副作用),并且对象 a 没有在 f() 中被销毁)是 NRVO(类似情况,如:https://stackoverflow.com/a/3906038/1857518 中所述)。

我的问题:

  1. 这个程序的输出是否符合 C++ 标准?
  2. 如果 (1) 为真,那么它属于以下哪种情况:
    • 输出将永远是这个
    • 存在一组合法且有限的输出,例如Out(例如|Out| &gt; 1)。并且一致的编译器可以从集合Out 中生成任何一个。如果是这样的话,Out 的集合是什么样子的。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您在此行为中看到的内容称为copy elision

    1.这个程序的输出是否符合C++标准?

    是的,允许编译器针对这种情况优化复制副作用。

    2.输出永远是这个

    没有。如前所述,编译器允许优化复制行为,但不一定需要这样做。

    因此,对于返回的“副本”,您不能依赖任何存在或删除的副作用。另见这篇文章:Is it possible to ensure copy elision?

    【讨论】:

    • 后续问题:是否有可能创建临时文件?我问的原因是因为这个页面msdn.microsoft.com/en-us/library/a8kfxa78.aspxThese temporaries are created only if your program does not copy the return value to an object. - 这是 MSVC++ 决定做的事情,还是 C++ 标准规定的事情?
    • @abi ' 这是 MSVC++ 决定做的事情,还是 C++ 标准要求做的事情?' 我想说的是第一个,标准并没有声称要实例化一个如果没有为 AFAIR 分配左值,则根本就没有临时对象。如前所述:在这种情况下,您不应依赖使用复制构造函数调用实现的副作用。
    猜你喜欢
    • 2011-10-04
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    相关资源
    最近更新 更多