私はそれに::delete
クラスを呼び込もうとしましたoperator delete
。しかし、デストラクタは呼び出されません。
私は、クラス定義されMyClass
、そのoperator delete
オーバーロードされているが。グローバルoperator delete
もオーバーロードされています。のオーバーロードoperator delete
はMyClass
、オーバーロードされたグローバルを呼び出しますoperator delete
。
class MyClass
{
public:
MyClass() { printf("Constructing MyClass...\n"); }
virtual ~MyClass() { printf("Destroying MyClass...\n"); }
void* operator new(size_t size)
{
printf("Newing MyClass...\n");
void* p = ::new MyClass();
printf("End of newing MyClass...\n");
return p;
}
void operator delete(void* p)
{
printf("Deleting MyClass...\n");
::delete p; // Why is the destructor not called here?
printf("End of deleting MyClass...\n");
}
};
void* operator new(size_t size)
{
printf("Global newing...\n");
return malloc(size);
}
void operator delete(void* p)
{
printf("Global deleting...\n");
free(p);
}
int main(int argc, char** argv)
{
MyClass* myClass = new MyClass();
delete myClass;
return EXIT_SUCCESS;
}
出力は次のとおりです。
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
実際:
のオーバーロードoperator delete
を呼び出す前に、デストラクターへの呼び出しは1つだけですMyClass
。
期待される:
デストラクタへの呼び出しは2つあります。のオーバーロードoperator delete
を呼び出す前の1つMyClass
。グローバルを呼び出す前の別のoperator delete
。
::delete p;
*p
のタイプが削除されるオブジェクトのタイプと同じではないため(または仮想デストラクタを持つ基本クラスではない)、未定義の動作が発生します
void*
、オペランドが明示的に不正な形式であることさえ知らなかった。[expr.delete] / 1: " オペランドは、オブジェクトタイプまたはクラスタイプへのポインタでなければなりません。[...]これは、voidがオブジェクトタイプではないため、タイプvoidのポインタを使用してオブジェクトを削除できないことを意味します。 * "@OP回答を修正しました。
MyClass::operator new()
(少なくとも)size
バイトのrawメモリを割り当てる必要があります。のインスタンスを完全に構築しようとするべきではありませんMyClass
。のコンストラクタMyClass
はの後に実行されMyClass::operator new()
ます。次に、delete
式inmain()
がデストラクタを呼び出し、メモリを解放します(デストラクタを再度呼び出すことはありません)。::delete p
発現は、オブジェクトの種類に関する情報がありませんp
ので、点をp
あるvoid *
ので、デストラクタを呼び出すことはできません。