為何存在未定義行為:透過基底指標刪除派生陣列
C 03 標準指定透過基底指標刪除物件陣列是未定義的行為。這是由於要刪除的物件的靜態類型和動態類型之間的差異造成的。
靜態型別與動態型別
指標的靜態型別是程式碼中宣告的型別,而動態型別是指向物件的實際型別。範例程式碼中:
<code class="cpp">struct B { virtual ~B() {} }; struct D : B {}; B* p = new D[20];</code>
p 的靜態型別為 B*,而 *p 的動態型別為 D。
未定義行為
標準規定,在第二種選擇(刪除陣列)中,如果動態類型與靜態類型不同,則行為未定義。這是因為 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中文網其他相關文章!