15

私はこのコードを持っています:

class Class {
public:
    virtual ~Class() {}
};

int main()
{
    Class* object = new Class();
    delete object;
}

これを Visual C++ 10 でコンパイルし、delete objectステートメントのこの逆アセンブリを取得します。

delete object;
test        eax,eax  
je          wmain+23h (401041h)  
mov         edx,dword ptr [eax]  
push        1  
mov         ecx,eax  
call        dword ptr [edx]

そしてこれは実際のデストラクタの場合:

Class::`scalar deleting destructor':
test        byte ptr [esp+4],1  
push        esi  
mov         esi,ecx  
mov         dword ptr [esi],offset Class::`vftable' (402100h)  
je          Class::`scalar deleting destructor'+18h (401018h)  
push        esi  
call        dword ptr [__imp_operator delete (4020A8h)]  
pop         ecx  
mov         eax,esi  
pop         esi  
ret         4

push 1呼び出しサイトで何をしているのかtest、デストラクタのエントリ ポイントで がその値をチェックし、条件付きで への呼び出しをバイパスするのはoperator delete()なぜですか?

4

3 に答える 3

15

この引数は、デストラクタが最後に delete を呼び出す必要があるかどうかを知るために使用されます。

呼び出したくない3つのケース:

  • デストラクタは、派生クラスのデストラクタによって呼び出されます
  • オブジェクトはスタックに割り当てられるため、new では作成されません。
  • オブジェクトは別のオブジェクトのフィールドであるため、new によって作成されません

編集:3番目のケースを追加

于 2011-11-08T14:54:12.787 に答える
6

基本的に、仮想デストラクタは呼び出し元の演算子 delete も実装します。パラメータは、それを呼び出すかどうかを決定するためにあります。

このような非表示のデストラクタ パラメータの意味を示すこの回答を参照してください。

于 2011-11-08T14:58:03.567 に答える
5

余分なパラメーターは、適切な継承レベルで、メモリの割り当てを一度だけ解除するように、どのデストラクタが最も派生したデストラクタであるかをコンパイラに伝えると思います。正しく思い出せば、gcc で似たようなものを見たことがあります。

于 2011-11-08T14:54:03.043 に答える