C ++コンパイラは、次の状況でデフォルトのコピーコンストラクタを合成します。(C ++オブジェクトモデルの内部から)
- コピーコンストラクターが存在するクラスのメンバーオブジェクトがクラスに含まれている場合。
- コピーコンストラクタが存在する基本クラスからクラスが派生した場合。
- クラスが1つ以上の仮想関数を宣言するとき
- クラスが、1つ以上の基本クラスが仮想である継承チェーンから派生している場合。
クラスAが4つの状況にないことがわかります。したがって、clはデフォルトのコピーコンストラクタを合成しないでください。たぶんそれが2つのtempAオブジェクトが構築され破壊された理由です。
分解ウィンドウから、A::Aが呼び出されていない次のコードを確認できます。:
B b;
00B317F8 lea ecx,[b]
00B317FB call B::B (0B31650h)
00B31800 mov dword ptr [ebp-4],0
func(b);
00B31807 mov al,byte ptr [ebp-12h]
00B3180A mov byte ptr [ebp-13h],al
00B3180D mov byte ptr [ebp-4],1
00B31811 movzx ecx,byte ptr [ebp-13h]
00B31815 push ecx
00B31816 call func (0B31730h)
しかし、デストラクタを仮想化するとします。次の逆アセンブルコードを取得します。A::Aが呼び出されていることがわかります。その後、結果は期待どおりになり、1つのオブジェクトのみが作成されます。
B b;
00331898 lea ecx,[b]
0033189B call B::B (03316A0h)
003318A0 mov dword ptr [ebp-4],0
func(b);
003318A7 push ecx
003318A8 mov ecx,esp
003318AA mov dword ptr [ebp-1Ch],esp
003318AD lea eax,[b]
003318B0 push eax
003318B1 call A::A (0331900h)
003318B6 mov dword ptr [ebp-20h],eax
003318B9 call func (03317D0h)