C ++删除指针

时间:2014-03-14 14:08:47

标签: c++ templates pointers struct

我正在编写一个程序,它使用指针和非尖头项的结构,我正在尝试正确地释放我的数据以减少开销(这确实很重要)。

这就是我所拥有的。我本质上是使用特定功能创建自己的队列。我的结构只包含一段通用数据和一个指向下一个位置的指针。

template<class T>
struct Spot
{
    T data;
    Spot *spotBehind;
};

当我添加新元素时,我会使用以下代码执行此操作(我会跟踪队列的头部和尾部)。

if(front == NULL)           //Make first head
    {
        Spot<T> *newSpot = new Spot<T>();
        newSpot->data = newElement;
        newSpot->spotBehind = front;
        front = newSpot;
        back = front;
    }
    else        //Find back of line and add
    {
        Spot<T> *newSpot = new Spot<T>();
        newSpot->data = newElement;
        newSpot->spotBehind = NULL;
        back->spotBehind = newSpot;
        back = newSpot;
    }

所以在这之后,当涉及到析构函数时,我当然需要为我拥有的每个 new 都有删除。所以我的析构函数使用代码:

Spot<T> *current = front;
Spot<T> *next = NULL;
while(current != NULL)
{
    next = current->spotBehind;

    delete current;
    current = NULL;

    current = next;
}

现在我关注的是这里。当我使用我的析构函数时,我不认为它正在做它应该做的事情,我可能在这里有内存泄漏。通过各种 cout 语句,我可以验证我的信息是否存储并按预期工作。但是当我删除数据时,它实际上似乎没有被删除。为了尝试调试它,我用以下内容替换了重构器代码(上面)以了解它正在做什么。

while(current != NULL)
{
    next = current->spotBehind;

    cout << "Before Delete " << current << " Data: " << current->data << endl;
    delete current;
    cout << "After Delete " << current << " Data: " << current->data << endl;
    current = NULL;
    cout << "After Null " << current << endl;
    current = next;
    if(current != NULL)
        cout << "After Reassigned " << current << " Data: " << current->data << endl;
}

我得到以下结果:

Before Delete 0x100103b20 Data: 5
After Delete 0x100103b20 Data: 5
After Null 0x0
After Reassigned 0x100103b30 Data: 10
Before Delete 0x100103b30 Data: 10
After Delete 0x100103b30 Data: 10
After Null 0x0

大问题

所以我的重要问题是,信息实际上是按照预期的方式解除分配的。我在想我做错了什么,因为在我的Spot指针上使用'delete'命令之后,我仍然可以看到值(以及spotBehind指针)。如果它按我想要的方式工作,我不应该看到垃圾值和一个空的spotBehind指针或者只是无法访问数据?我很感激有人向我解释这个问题,如果我这样做不正确,有人会建议一种正确删除信息的方法吗?

2 个答案:

答案 0 :(得分:2)

我认为您的代码按预期工作。

删除正常后数据仍然存在,因为删除并不意味着必须覆盖它。 delete只告诉内存管理指针指向的内存不再被使用,可以重新分配。在该操作之后访问它是非法的并且可能导致未定义的行为,但大多数情况下可能没有任何访问冲突,因为该地址仍然指向应用程序堆。

答案 1 :(得分:2)

内存分配通常使用某种链表实现。自由操作标记块可用于系统。 通常,释放内存将取决于编译器和构建类型 - 您是否在Debug of Release中打印了这些值?

例如,调试模式下的MS编译器通过

填充释放的块
memset(pHead, _bDeadLandFill,  // 0xdddddddd

此处0xdddddddd是编译器用于标记freed memory的特殊值。

尝试打印已删除指针的数据会导致Access violation错误。 您可以尝试调试operator delete以查看它在系统中的实现方式。