web-dev-qa-db-ja.com

voidポインターを削除する方法?

C++でこのようなオブジェクトを削除するときに問題はありますか?

MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
38
user3277361

書面によるとこれは合法です。

MyCls*へのキャストバックは重要です。それがないと、未定義の動作が呼び出されます-MyClsデストラクタは呼び出されず、他の問題(クラッシュなど)も発生する可能性があります。正しい型にキャストバックする必要があります。

また、複数の継承が含まれ、複数のキャストが使用される場合、これは複雑になる可能性があることに注意してください。キャストはどちらの方向でも「一致」する必要があります。

破棄時に型がわからないようにコードが構造化されている場合は、削除可能な各オブジェクトに、仮想デストラクターを備えた共通の基本クラスを指定します。次に、削除が呼び出される前に基本クラスにキャストします。

72
StilesCrisis

コードは明確に定義されています。両方のキャストは静的キャストですが、Cスタイルのキャストを使用する代わりに、これを明示的に(static_cast<void*>etc。)するのが良いスタイルです。標準では、オブジェクトへのポインターがvoidポインターに変換され、静的キャストによって戻された場合、元の値を維持するとしています。したがって、最終的なdelete式はdelete cと同じ効果を持ちます。

そうは言っても、void*の使用は、多くの場合、C++のコード臭です。

32
Brian

削除後にポインタをnullptrに設定することをお勧めします。特に、別のスレッド/イベントハンドラでのアクセス違反/ segfaultを回避するためです。

_auto c = new MyCls();
auto p = static_cast<void*>c;
delete static_cast<MyCls*>p;
p = nullptr;
c = nullptr;
_

スマートポインターを使用し、new/deleteを完全に回避することをお勧めします。

_{
    auto c = std::make_unique<MyCls>();
    auto p = static_cast<void*>(c.get());
    // no need to delete p
} // c will be released automatically during unwinding
_

C++では、_static_cast_などの明示的なキャストが推奨されます。

~MyCls()が重要な場合、pを_MyCls*_にキャストするため、呼び出されます。 _void*_を削除してもデストラクタは呼び出されず、メモリリークやその他の問題が発生する可能性があります。

0
TimTim Wong