8

このコードを VS2010 で実行すると、NRVO が適用されません。

#include <stdio.h>

class A
{
    public:

    A() { printf( "I am in constructor\n" ); }
    A(const A& a) { printf( "I am in copy constructor\n" ); }
    ~A() { printf( "I am in destructor\n" ); }
    int i;       
};

A f(int j)
{
    A a;
    if ( j )  return a;
    a.i = j;
    return a; 
}

int main()
{
    A a;
    a = f(5);
}

編集:これはデストラクタと関係があります。その行をコメントアウトすると、NRVO が使用されます。しかし、これはなぜですか?

4

2 に答える 2

6

ここで NRVO が適用されないのはなぜですか?

これが純粋な好奇心であり、VC10 が NRVO を実行するかどうかをアルゴリズム的に決定する方法を知りたい場合、この質問に確実に答えることができるのは、VC10 が内部でどのように機能するかを知っている人、つまりそれを書いた人だけです。

私が言えることは、C++11 標準によれば、コンパイラはこの状況で NRVO を実行することが許可されており、そうしないのは単なるコンパイラの決定であり、有効性の制約によるものではありません。パラグラフ 12.8/31 によると:

[...] コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。

クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ非揮発性自動オブジェクト (関数または catch 句のパラメーター以外) の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます

[...]

ただし、コンパイラに NRVO を実行させることができるはずだと期待して尋ねている場合、答えは「できません」です。

NRVO を適用するかどうかは、完全にコンパイラの裁量に任されています。あなたはそれを期待することはできませんし、それが実行されないことを期待することもできません. これは、私の知る限り、いわゆる「as-if」ルールの唯一の例外です。

つまり、最適化のレベルを上げると、NRVO が実行される可能性が高くなります。

于 2013-04-16T13:37:23.560 に答える
1

お使いの環境で何が表示されるかはわかりませんが、これは GCC で期待どおりに機能します (たとえば、こちらを参照してください)。

普通:

I am in constructor
I am in constructor
I am in destructor
I am in destructor

-fno-elide-constructors:

I am in constructor
I am in constructor
I am in copy constructor
I am in destructor
I am in destructor
I am in destructor
于 2013-04-16T13:38:11.330 に答える