0

次のコードがあります。

    struct balls
    {
        int mNumBalls;

        ~balls();    
    };

    inline balls::~balls()
    {
          // is not called in VS2010 when getBalls returns in monkey constructor
    }

    balls getBalls()
    {
        balls myBalls;

        myBalls.mNumBalls = 5;

        return myBalls;
    }

    struct monkey
    {
        balls mBalls;

        monkey();
    };

    inline monkey::monkey() : mBalls(getBalls())
    {
    }

VS2010 デバッガーにステップインすると、コンストラクターで戻るballsときにデストラクタが呼び出されないことに気付きました。これは C++ 標準で定義されていますか、それとも VC++ にのみ存在する最適化ですか? この場合、クロスプラットフォームで呼び出されていないデストラクタに頼ることはできますか?getBalls()monkey()

ありがとう

4

3 に答える 3

2

明確に定義されたメカニズムであるコピーの省略に対応しています。不要なコピーを実行しないのは実装次第です。

于 2013-03-09T20:21:33.303 に答える
2

複雑な構造を値で返したい場合、不必要な構築と破棄を回避する唯一の保証された方法は、移動セマンティクスを使用することです。方法:移動コンストラクターを作成するを参照してください。

たとえば、クラスがメモリを割り当てる場合、moveコンストラクタを使用すると、メモリの所有権をある変数から別の変数に譲渡できます。次に、オプティマイザーは、転送された変数の冗長ストアとnullチェックを削除します。

于 2013-03-09T20:26:35.290 に答える
1

C++11 標準のパラグラフ 12.8/31 によると:

特定の基準が満たされている場合、コピー/移動操作用に選択されたコンストラクターおよび/またはオブジェクトのデストラクタに副作用がある場合でも実装はクラス オブジェクトのコピー/移動構築を省略できます。このような場合、実装は、省略されたコピー/移動操作のソースとターゲットを、同じオブジェクトを参照する 2 つの異なる方法として扱い、そのオブジェクトの破棄は、2 つのオブジェクトが削除された時点のいずれか遅い方の時点で発生します。最適化なしで破壊されました。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます(複数のコピーを排除するために組み合わせることができます)。

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

— [...]

これはそれらのケースの 1 つです。

balls getBalls()
{
    balls myBalls;

    return myBalls; <== COVERED BY THE QUOTED PARAGRAPH
//  ^^^^^^^^^^^^^^
}

これは、一般的な " as if " ルールの例外を表すという点で、非常に重要です。「as if 」ルールは、基本的に、結果が同じである限り、コンパイラが記述したコードを変更することを許可します(「as if」は、記述したプログラムを正確に実行します)。

ただし、この場合、コピー コンストラクター、ムーブ コンストラクター、またはデストラクタに副作用があっても、コンパイラがテンポラリを作成する (またはテンポラリを作成しない!) ことに依存することはできません。

于 2013-03-09T20:24:45.540 に答える