char* pChar = new char[10];
delete pChar; // this should not work but it has same effect as
// delete[], WHY?
// I know this is illegal, but why does it work?
5 に答える
同じ効果があるように見えるかもしれませんが、そうではありません。配列の型が抽象データ型 (つまり、クラス) の場合、最後の 9 つの要素のデストラクタは呼び出されません。
あなたは運が良かったからです。これは未定義の動作です。未定義の動作の 1 つの可能性は、何か悪いことが実際に起こったとしても、何も悪いことが起こっていないように見えることです。後でないとわからないかもしれません。
プリミティブ型が安全であることに期待することはできません。これを読んでください(コメントでJames Rothによってリンクされています):https://isocpp.org/wiki/faq/freestore-mgmt#delete-array-built-ins
うまくいきません。それは単に機能しているように見えます。未定義の動作を示すコードは、一見すると「機能している」ように見える場合があります。これは、バグに満ちたプログラムが、不適切に選択されたテスト スイートで「正常に機能する」ように見える場合と同じです。
未定義の動作です。そして、「今回は動く」というのは「未定義」の範疇に入るから、あるプラットフォーム、あるコンパイラで動く可能性がある。それでも、やるべきではありません。そのようなデストラクタを使用してオブジェクトの配列の割り当てを解除し、デストラクタが呼び出されるかどうかを確認しましたか?
編集:あなたのコメントによると、あなたは...
Microsoft Visual Studioのほとんどのバージョンでは、これは実際には正しく機能します。ただし、これが必要な理由はありません。完全にプラットフォーム次第です。
delete []の背後にある考え方は、これがコンパイル時にサイズが不明な特殊なケースであり、割り当てフレームワークが別の方法で処理する(そして削除ケースを最適化する)可能性があるということです。
厳密に言えば、delete pointerToBaseClass
コンパイル時にサイズもわかりませんが、これは仮想テーブルによって解決され、コンパイラはクラスがコンパイル時にポリモーフィックであることを認識しています。
delete []を誤って処理すると、アロケータ(デバッガ、あらゆる種類の境界チェッカーなど)やユーザーが使用する可能性のあるカスタムアロケータを置き換えるツールで問題が発生する可能性があります。