未定義の動作の理由: ベース ポインターを介して派生配列を削除する
C 03 標準では、ベース ポインターを介して派生オブジェクトの配列を削除することを指定しています。未定義の動作です。これは、削除されるオブジェクトの静的型と動的型の違いによるものです。
静的型と動的型
ポインターの静的型は、動的型はコード内で宣言された型であり、動的型は指すオブジェクトの実際の型です。コード例:
<code class="cpp">struct B { virtual ~B() {} }; struct D : B {}; B* p = new D[20];</code>
p の静的型は B* ですが、*p の動的型は D です。
未定義の動作
標準では、2 番目の選択肢 (配列の削除) では、動的型が静的型と異なる場合の動作は未定義であると規定されています。これは、p が D 要素の配列の先頭を指していないためです。これは、最初の要素の B サブオブジェクトを指します。したがって、delete [] p; で削除します。は無効です。
実装に関する考慮事項
実装でこのルールを強制するには、コンパイラが配列の動的型を決定し、p をその型に動的にキャストする必要があります。削除する前に。ただし、ポリモーフィズムが使用されていない場合、これにより不要なオーバーヘッドが発生します。
ポリモーフィックな配列
ポリモーフィックな動作を持つ配列が必要な場合は、 C の既存の機能を使用した独自の実装。たとえば、派生オブジェクトへのポインターの配列をラップするクラス テンプレートを作成できます。
<code class="cpp">template <typename T> class PolymorphicArray { public: PolymorphicArray(size_t size) : _size(size), _data(new T*[_size]) {} ~PolymorphicArray() { delete[] _data; } T*& operator[](size_t index) { return _data[index]; } private: size_t _size; T** _data; };</code>
このクラスを使用すると、標準に違反することなく、派生オブジェクトの配列に対してポリモーフィックな動作を使用できます。
以上がベース ポインターを介した派生配列の削除が C で未定義の動作になるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。