2012-02-12 28 views
5

次のコードは、デストラクタ4回呼び出して呼び出しますか? 私は3つのデストラクタコールしかないはずだと考えていました。戻り値の最適化 - - C++デストラクタは

+0

いいえ、そうではありません。 http://ideone.com/ywGdo –

+0

おっと!私はCodepadを使いました.. http://codepad.org/1OJGoYGP – Venky

+0

C++に関する質問に「c」を付けないでください。言語は同じではありません。 – tinman

答えて

1

コンパイラは最適化しませんでした。最適化を有効にしてコンパイルしましたか? main()で2つのオブジェクトがあります

A 
A 
F 
A 
~A 
~A 
~A 
8

ので、デストラクタは、という理由だけで、それらの回呼び出されます。ここでは

は、同じコードの出力、gccでコンパイルされています。 f()のオブジェクトの1つで、デストラクタは という1つで、と呼ばれます。合計3回(期待通りですが、読み込み中...)

fから戻ったときに作成される一時オブジェクトに対して4回目のデストラクタが呼び出されました。これは、RVOがまったくない場合にのみ発生します。 RVOはコンパイラの選択です。つまり、コンパイラが最適化するか、コンパイルできない可能性があります。この言語はRVOの保証をしません。

とにかく、最適化レベルを上げてください。あなたは3つのデストラクタ呼び出ししか見ることはできません。

0

RVOを使用することはできません。そのため、デストラクタやコピーコンストラクタ内に関数ロジックを置くべきではありません(そうです、それらも省略できます)。

戻り値の最適化は、標準で許可されているものですが、強制しません。

最適化やO2を使用しないと、私も4つのデストラクタ呼び出しを取得します。あなたが機能f()から戻っているときに、オブジェクトbの一時的なコピーが作成されます。完全な最適化と

- - 牛私は3

+0

/O2にもNRVOが含まれています。つまり、デストラクタは3つしか呼び出されません。 http://msdn.microsoft.com/en-us/library/8f8h5cxt.aspxを参照してください。 – LihO

+0

@LihO私はコードをテストしました。だから私はあなたが言うことが正確であれば、MSVSにバグがあると思います。 –

+0

私もテストしました(MSVS2010)。最適化を無効にすると( '/ Od')、4つのデストラクタが呼び出されます。 '/ O1'または'/O2'では、3つのデストラクタが呼び出されます。 – LihO

1

Aのインスタンスの1つの隠れ創造と破壊がありますを取得します。それはbに割り当てられ、main()になり、その後破棄されます。

+0

彼はRVOが起こらない理由を尋ねています。 –

+0

@Luchianあなたが正しいですが、使用された最適化レベルは言及されていないので、私は価値あるもので戻ってきたときに一時的に見落とした印象を受けました。 –

0

fのローカル変数は、関数が戻るときに一時変数にコピーされます。そのため、4つのデストラクタ呼び出しがあります。 (コピー操作は、コピーコンストラクタA(A&)なく、あなたのデフォルトコンストラクタA()、それ故に3 A秒を呼び出します。)

+0

それは問題ではありません。彼は戻り値の最適化がなぜ適用されないのか尋ねています。 –

+0

私は彼/彼女がRVOを知っているか分からない。問題は単に「3つではなく4つのデストラクタ呼び出しがあるのはなぜですか?」私はそれに答えた。 –

+0

タイトルを読んだことがありますか? –

3

メインで2つのオブジェクトがありますA a,b;、1つの目的は、機能f()のボディに:A b;、その後、一時オブジェクトそれがありますがコピーされ、そのコピーがbに格納されています。

関数の本体にbを返すと、最初にコピーが作成された後、ローカルbが破壊され、copyが変数bに割り当てられ、このコピーが破棄されます。

クラスA定義に次の行を追加して、自分自身を参照してください。コンパイラは、冗長コピーコンストラクタを排除しようとデストラクタが機能f()からローカルbが割り当てられることを意味しを呼び出しNamed Return Value Optimization

A(const A&) { cout << "copying" << endl; } 

を、コピーを作成せずにメインの変数bに書き込んでください。したがって、RVO/NRVOでは、3つのオブジェクトしか作成されません。

あなたのケースでRVOせずにこのコピーを破壊避けるためにどのような方法がありますが:

A a; 
A b = a.f(); 

この場合、機能f()の戻り値のコピーが変数bとして作成されて記憶されます。また、アサイメント演算子が呼び出されず、メインには2つのオブジェクト(aおよびb)が返されます。f()が返されます。

これが役に立ちます。