1

以下のコードでは、実行がからBに戻ったときに、クラスのデストラクタがケース1で呼び出されますが、ケース2では呼び出されません。で作成されたときに両方がヒープメモリ上にあるため、この違いはわかりません。説明してもらえますか?mainfn()Anew

class B {
public:
    B() {
        printf(" [B] COntsructor");
    }
    ~B() {
        printf(" [B] Destructor");
    }
};

class A {
public:
    A() { 
        printf(" [A] COntsructor");
    }
    ~A() { 
        printf(" [A] Destructor");
    }

    B Query() { return b; }    /// Case 1
    B* Query() { return &b; }  /// Case 2

    B b;
};

void fn()
{
    A *a = new A();
    B b = a->Query();  // case 1
    B* b = a->Query(); // case 2
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
    fn();
    return 0;
}
4

4 に答える 4

3

ケース1:値で返すb場合、ローカル変数bはコピーコンストラクターを使用して作成されます。1つのコピーを除くすべてが、戻り値の最適化によって最適化されます。ローカル変数が破棄されると、bデストラクタがトリガーされます。

ケース2:あなたが返すとき&b、あなたが返すのはへのポインタでbあり、したがって破壊は必要ありません

編集:コードは、コンストラクターへの対応する呼び出しなしで呼び出されているデストラクタを示しています。これは、関数returncopyがコピーコンストラクターを介して行われているためです。

Edit2:@ZarShardanは正しいです-私が参照した「多くのコピー」は、戻り値の最適化のおかげでおそらく存在しないでしょう。

于 2013-01-07T06:42:55.827 に答える
1
  • a削除されることはないため、それまたはそのメンバーのデストラクタはありません。
  • a->bデフォルトのコンストラクターを使用して構築されるため、それがコンストラクター呼び出しです。
  • B b = a->Query();何も出力しないコピー コンストラクターを使用して作成されます。
  • 最後にfnlocalbがスコープ外になるので、それがデストラクタの呼び出しです。

コピー コンストラクターのデバッグ コードを追加したり、すべてのデバッグ コードで の値を出力したり、最終的にそれらのデストラクタ呼び出しを確認するためthisに削除したりすると、状況がより明確になる可能性があります。a

于 2013-01-07T06:51:05.437 に答える
0

new2 番目のケースでは のインスタンスを作成していないBため、 A がメンバとして保持するポインタは のデストラクタでクリーンアップされA、 のコンストラクタBが呼び出されなかったため、デストラクタも呼び出されません。

于 2013-01-07T06:48:43.160 に答える
-1

オブジェクト a は決して削除されないため、それ自身のデストラクタもそのメンバー オブジェクトのデストラクタも呼び出されません。

追加してみる

delete a; 

関数 fn() の最後に

または、裸のポインターの代わりに std::unique_ptr を使用することをお勧めします。Query メンバー関数が例外をスローした場合 (RAII のもの) に備えて、それはより良い設計です。

于 2013-01-07T06:47:47.600 に答える