2013-04-08 159 views
0

我正在閱讀C++中的思考,第13章:動態對象創建。 在本章中,Eckel談論刪除void *可能是一個錯誤。 以下段落讓我困惑。在C++中刪除void *指針

另一個內存泄漏問題與確保刪除爲容器中保存的每個對象指針實際調用的 有關。 容器不能「擁有」指針,因爲它將其作爲void *和 因此無法執行正確的清理。用戶必須負責清理物體 。如果 添加指向堆棧上創建的對象的指針,並且在 堆上創建的對象位於同一個容器,因爲刪除表達式不安全 對於尚未分配到堆上的指針,則會產生嚴重問題。

任何人都可以解釋爲什麼「添加指向堆棧上創建的對象的指針和在堆上創建的對象到同一個容器」會產生嚴重的問題嗎?

爲了使問題更清楚,我添加了相關的代碼片段。

class Stack { 
    struct Link { 
    void* data; 
    Link* next; 
    void initialize(void* dat, Link* nxt); 
    }* head; 
public: 
    void initialize(); 
    void push(void* dat); 
    void* peek(); 
    void* pop(); 
    void cleanup(); 
}; 
+2

我相信你誤解了意思。這是說你不能刪除一個'void *'到一個非平凡的對象**,並單獨**表明你不能刪除可能指向堆棧的指針。 – 2013-04-08 16:34:42

+0

可能重複[是否安全刪除無效指針?](http://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer) – bobobobo 2013-05-07 00:55:28

回答

2

作爲一般規則堆棧上的對象不需要被刪除,堆上的對象需要。如果您將它們放在同一個容器中,您如何跟蹤要刪除哪些容器?您最好有兩個容器,一個用於堆棧中的對象(不需要刪除的對象),另一個用於堆中的對象(需要刪除的對象)。

+2

或者更好的是,讓容器處理您的分配,以便您不需要手動調用刪除 - RAII。 – 2013-04-08 16:38:59

0

這段確實有點含糊。它混合了兩個不同的問題,並導致混亂,在我看來。

  1. 爲了正確刪除一個對象,編譯器必須知道它的類型。對於void*,類型未知(這正是使用void* - 隱藏實際類型的要點)。因此,如果不轉換爲適當的實際類型,則無法在此對象上執行刪除操作。
  2. 通常使用void*意味着所指向的對象的所有權屬於某個外部實體設計,而不是包含指針的實體。在實體內部,指針是不透明的,並且充當外部對象的處理程序,就實體而言這是一個黑盒子。類必須清楚責任劃分,並且不能試圖摧毀void*對象,因爲它不知道它的生命週期(例如,試圖釋放堆棧變量),也不知道應該完成的操作破壞後(導致功能不正確)。