具有派生物件的陣列:Delete[]的陷阱
C 標準明確指出,使用基數刪除導致派生物件陣列指標的行為。這個看似模稜兩可的規則引發了對其基本原則和潛在意義的質疑。
為了理解這個概念,讓我們回顧一下靜態類型和動態類型之間的差異。假設我們有以下程式碼片段:
<code class="cpp">struct B { virtual ~B() {} }; struct D : B {}; B* p = new D();</code>
在這種情況下,p 的靜態型別是 B*,而 *p 的動態型別是 D。這是因為 p 指向型別的子物件D 已被建構來取代 B 物件。
但是,當我們使用基底指標宣告陣列時,會出現微妙的差異。考慮以下程式碼:
<code class="cpp">B* p = new D[20];</code>
這裡,p 指向數組中第一個元素的基子對象,而不是第一個元素本身。因此,使用delete [] p違反了數組的靜態和動態類型匹配的要求。
這種未定義行為的原因在於它會為執行時間環境帶來潛在的低效率和複雜性。若要使用基底指標正確刪除派生物件的陣列,實作需要動態檢索陣列的元素類型,並將每個指標轉換為正確的類型,然後再執行刪除。這種開銷被認為是不必要的,特別是考慮到多態性數組的有限用例。
此外,使用基底指標刪除派生陣列會帶來另一個問題。由於 p 指向子對象,因此對陣列元素的後續存取(例如,i > 0 時的 p[i])將產生不正確的結果。這進一步支援了派生物件數組使用帶有基底指標的delete []的限制。
總之,使用基底指標刪除派生物件陣列的未定義行為源自於其固有的複雜性和缺乏它會帶來的實用性。雖然可以實現專門的刪除[]來處理這種情況,但它會付出成本效益和可用性的代價,與 C 的設計理念不一致。
以上是為什麼在 C 中刪除具有基底指標的派生物件陣列是未定義的行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!