1

Base* optr=new Derived();

delete optr;

optrBaseクラスに非仮想デストラクタがある場合、ポインタを削除するときに呼び出されるのは〜Base()デストラクタだけであることを私は知っています。しかし、〜Derived()デストラクタが呼び出されなくても、DerivedObjectによって取得されたメモリが解放されていることがわかりました。だから私の質問は、オブジェクトをデストラクタと呼ばずに解放できるかということです。

答えが「はい」の場合、Derivedクラスに動的に割り当てられた変数が含まれていないので、呼び出されなくてもかまわないので、非仮想デストラクタを使用できますか?

4

5 に答える 5

4

標準のC++の観点からは、答えは単純です。結果は未定義の動作であるため、得られるものは完全に予測不可能です。

とにかく気にする理由は少し戸惑います。クラスからすべての仮想関数を削除できる場合、各インスタンスは(vtableポインターのサイズだけ)小さくなります。ただし、基本クラスとしてこのようなものを使用することはほとんど意味がありません。基本クラスとして使用するのが賢明であるためには、派生クラスをオーバーライドするために、基本に少なくとも1つの仮想関数が必要です。仮想関数(任意の仮想関数)を作成すると、基本的に無料で追加できます。仮想関数を追加しても、オブジェクトが大きくなることはありません。

質問に直接答えるには:はい、デストラクタを呼び出さなくてもメモリを解放できます。本当の問題は、それを実現したときに何が起こるかということです(そして、その質問に対する答えは実際にはありません)。

于 2012-04-16T16:04:54.770 に答える
2

未定義の振る舞いについてのことは、時々それがうまくいくように見えるということです。

標準では、基本クラスのデストラクタが仮想でない場合はプログラムが失敗する必要があるとは言われていませんデストラクタ仮想の場合はプログラムが機能する必要があるとされています。

于 2012-04-16T16:04:47.423 に答える
1

派生クラスがメンバーを追加しない場合は、仮想デストラクタなしで逃げることができる場合がありますメモリフットプリントは同じになり、メンバーはすべて基本クラスのデストラクタで破棄されます。ただし、これは標準によって保証されているわけではなく、コンパイラの実装に翻弄されることになります。

于 2012-04-16T16:02:00.053 に答える
1

オブジェクトデストラクタの呼び出しとメモリの解放という2つの明確なことがあります。

標準のヒープ仕様では、メモリブロックを解放するときにメモリブロックサイズを渡す必要はありません。つまり、ヒープの実装では、メモリブロックのサイズ自体を推測する必要があります。

したがって-はいDerived適切な手段で破棄する必要のある余分なもの(ヒープに割り当てられたメモリ、ファイルハンドルなど)が含まれていない場合は、仮想デストラクタは必要ありません。

于 2012-04-16T16:02:55.617 に答える
0

ここを見てください:仮想デストラクタ

于 2012-04-16T15:57:46.273 に答える