2013-04-08 141 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*对象,因为它不知道它的生命周期(例如,试图释放堆栈变量),也不知道应该完成的操作破坏后(导致功能不正确)。