0
  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由给定 struct 描述的数组key_node

Key main 本身是一个动态数组,但为了代码的缘故,我已经将它展示为一个静态数组。

假设数组有 3 个索引长,0,1,2每个索引包含一个单独的链表。现在我正在尝试删除每个链接列表,但似乎有些正在被删除,而有些则没有。

如何解决这个问题?

4

3 回答 3

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;
};

要将指针存储在 a 中unique_ptr,请使用reset(new Package_Node()). 而不是delete,调用reset()unique_ptr删除 a时,会自动删除a 指向的任何内容unique_ptr

这是 C++11——在 C++03 中,您可能有std::tr1::unique_ptr, 或boost::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;
            }

请注意,nPointer3并且nPointer4应该在 的开头保存相同的数据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拥有指针的 a 也应该在其析构函数中销毁它,如果它不拥有该指针,则应该使用其他指针。 RAII是你的朋友。当你创建一个拥有指针的 a 时,不要忘记遵循三原则。struct

于 2013-03-18T15:25:57.987 回答
1

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

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

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

于 2013-03-18T17:00:03.380 回答
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;
    }
}
于 2013-03-18T16:05:36.943 回答