派生オブジェクトを含む配列: Delete[]
C 標準では、ベースを使用して派生オブジェクトの配列を削除すると明示的に規定されています。ポインタは未定義の動作を引き起こします。この一見曖昧なルールは、その理論的根拠と潜在的な影響に関して疑問を引き起こしています。
この概念を理解するために、静的型と動的型の区別を確認してみましょう。次のコード スニペットがあるとします。
<code class="cpp">struct B { virtual ~B() {} }; struct D : B {}; B* p = new D();</code>
この場合、p の静的型は B* ですが、*p の動的型は D です。これは、p が型のサブオブジェクトを指しているためです。 B オブジェクトの代わりに構築された D。
ただし、ベース ポインターを使用して配列を宣言すると、微妙な違いが現れます。次のコードを考えてみましょう。
<code class="cpp">B* p = new D[20];</code>
ここで、p は、最初の要素自体ではなく、配列内の最初の要素の基本サブオブジェクトを指します。したがって、delete [] p の使用は、配列の静的型と動的型が一致するという要件に違反します。
この未定義の動作の理由は、実行時環境に潜在的な非効率性と複雑性が生じることにあります。ベース ポインターを使用して派生オブジェクトの配列を正しく削除するには、実装では、削除を実行する前に配列の要素の型を動的に取得し、各ポインターを正しい型にキャストする必要があります。特に多態性配列の限られた使用例を考慮すると、このオーバーヘッドは不要であると考えられます。
さらに、ベース ポインターを使用して派生配列を削除すると、別の問題が発生します。 p はサブオブジェクトを指しているため、配列の要素への後続のアクセス (たとえば、i > 0 の場合は p[i]) は誤った結果を生成します。これにより、派生オブジェクトの配列に対してベース ポインターを使用して delete [] を使用することに対する制限がさらにサポートされます。
結論として、ベース ポインターを使用して派生オブジェクトの配列を削除する未定義の動作は、固有の複雑さと欠如に起因しています。それがもたらす実用性。このケースを処理する特殊な delete [] を実装することは可能かもしれませんが、コストパフォーマンスと使いやすさが犠牲になり、 C の設計哲学と矛盾します。
以上がベース ポインターを持つ派生オブジェクトの配列の削除が C で未定義の動作になるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。