删除动态链表时遇到问题?

时间:2013-03-18 15:24:48

标签: c++ dynamic-arrays

  struct Package_Node
    {
        int bar_code;
        float package_weight;
        Package_Node *next_packaged;
    };

    struct Key_Node
    {
        int key;
        Package_Node *next_package;
    };        

   for(int i=0; i<3; i++)
            {
                if(keyMain[i].next_package==NULL)
                {
                    continue;
                }

                if(keyMain[i].next_package!=NULL)
                {
                    nPointer3=keyMain[i].next_package;
                    nPointer4=keyMain[i].next_package;
                    while(nPointer3)
                    {
                        nPointer4=nPointer4->next_packaged;
                        delete[] nPointer3;
                        nPointer3=nPointer4;
                    }
                }
            }

keyMain一个由给定结构key_node描述的数组。

Key main本身是一个动态数组,但为了代码,我将它显示为一个静态数组。

假设数组长度为3个索引0,1,2,并且每个索引都包含一个单独的链表。现在我试图删除每个链接列表,但似乎有些被删除而其他人没有删除。

如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

你在这里做错了什么?首先,您手动管理内存。

#include <memory>

struct Package_Node
{
  int bar_code;
  float package_weight;
  std::unique_ptr<Package_Node> next_packaged;
};

struct Key_Node
{
  int key;
  std::unique_ptr<Package_Node> next_package;
};

要在unique_ptr中存储指针,请使用reset(new Package_Node())。而不是delete,请致电reset()。删除unique_ptr后,unique_ptr指向的任何内容都会自动删除。

这是C ++ 11 - 在C ++ 03中,您可能有std::tr1::unique_ptrboost::unique_ptr,但没有移动语义unique_ptr使用起来更危险。


现在,如果您执行上述操作,您的代码会变得更短,并且取消分配整个链接列表只需.reset()指向第一个节点的智能指针:其他所有内容都会自动删除!

但是,您可能不愿意这样做。所以我会在你的代码中攻击其他一些问题。

您的变量名称不反映值的用法。 nPointer4是一个可怕的变量名称。请尝试记录其目的的PointerToDelete。此外,您应该在初始化点声明指针,并在它无效时清除它,而不是在它使用之前或之后使用它。 (重复使用变量没有获得奖励积分。)

看看这个循环:

            nPointer3=keyMain[i].next_package;
            nPointer4=keyMain[i].next_package;
            while(nPointer3)
            {
                nPointer4=nPointer4->next_packaged;
                delete[] nPointer3;
                nPointer3=nPointer4;
            }

请注意,nPointer3nPointer4应该在while的开头保留相同的数据,那么为什么它们都存在?你可以通过这样重写来减半你的状态:

            Package_Node* ptrToDelete=keyMain[i].next_package;
            while(ptrToDelete)
            {
                Package_Node* nextPtr = ptrToDelete->next_packaged;
                delete ptrToDelete;
                ptrToDelete = nextPtr;
            }

注意ptrToDelete仅在初始化时才存在。

注意nextPtr如何尽可能短的存在,然后超出范围。它只在初始化后才存在。

接下来,总是发布实际演示问题的编译代码。上面的代码不会因为与你的问题完全无关的原因而编译,读你的思想并不是你应该让别人去做的事情。

你不知道出了什么问题,所以你怎么知道什么是重要的?简单:让你的编译器搞清楚。制作一个简单的示例,演示您遇到的问题,编译它,测试问题是否仍然存在,然后发布

而不是出现问题,删除部件以缩短部分,发布可能存在或可能不存在问题的非编译代码,并希望其他人可以阅读您的想法。

您完全没有必要使用struct Package_Node* - Package_Node*更短,并且(除了一些极端极端情况)完全相同。

即使您不使用智能指针,拥有指针的struct也应该在其析构函数中销毁它,如果它不拥有指针则应该是其他东西。 RAII是你的朋友。当你拥有一个拥有指针的struct时,不要忘记关注rule of three

答案 1 :(得分:1)

我不知道你是如何检查事情是否已被删除;一旦你释放了内存,那个内存就可以被重用了,你不能再被允许访问了 - 虽然没有人会阻止你,除非你造成运行时错误 - 但是内存的内容不会被重新分配修改。 /> 您无法通过检查确定特定对象已被解除分配。

我相信您的问题是,当您完成后,您忘记将keyMain[i].next_package设置为NULL

for(int i = 0; i < 3; i++)
{
    if (keyMain[i].next_package != NULL)
    {
        Package_Node* current = keyMain[i].next_package;
        Package_Node* next = 0;
        while (current)
        {
            next = current->next_package;
            // No "[]" since you're apparently not allocating with "[]"
            delete current;
            current = next;
        }
        keyMain[i].next_package = NULL;
    }
}

答案 2 :(得分:1)

由于您在评论中提到nPointer3内存是通过“new Package_Node”分配的,因此行“delete [] nPointer3;”应阅读:

delete nPointer3;
nPointer3 = NULL;  // recommended (mentioned in another answer)

您描述的行为可能是由于尝试释放通过singular new分配的nPointer3内存时的未定义行为。只有通过数组new运算符“new []”分配的内存(例如新的Package_Node [16])应该与“delete []”一起发布。