关于c ++中链接列表/指针的问题

时间:2011-02-02 16:10:10

标签: c++ pointers

C ++中指针为NULL的性质似乎是随意的。我确信有一种方法可以让我失踪,但以下内容对我有意义,但似乎不起作用。我有以下方法将节点添加到链表:

LLNode *ll; // set to NULL in constructor.
void addToLL(Elem *e)
{
    LLNode *current = ll;
    while(true)
    {
        // edge case of an empty list.
        if (ll == NULL)
        {

            ll = new LLNode(e);
            break;
        }
        else if (current == NULL)
        {
            current = new LLNode(e);
            break;
        }
        else {
            current = current->next;
        }

    }
}

将第二个节点添加到列表时,current == NULL的情况不会被捕获,因此它会尝试调用current = current->next并且崩溃会访问无效内存。为什么会这样呢? LLNode具有指向Elem的指针,以及在另一个LLNode旁边调用的指针。

4 个答案:

答案 0 :(得分:4)

您可能没有在next构造函数中将NULL指针设置为LLNode

C ++中基本类型的对象(指针类型,数字类型等)具有不确定的初始值:默认情况下不会初始化它们。您需要在使用它们之前显式初始化这些对象。

答案 1 :(得分:3)

对于这类事情,你需要一个指向指针的指针,以消除实现中的许多不必要的异常:

LLNode *ll = NULL;

void addToLL(Elem *e)
{
  LLNode** current = ≪

  // While the current pointer to pointer is mapped to something,
  // step through the linked list.
  while (*current)
    current = &(*current->next);

  // At this point current is pointing to a NULL pointer and can
  // be assigned to.
  *current = new LLNode(e);
}

指针为NULL的原因是因为它的计算结果为false,并允许您进行简单检查,例如while (*current),而不会产生大量开销。在CPU中,这通常最终被实现为零测试操作。

指针只有在初始化时才为NULL。在C中,除非正确初始化并引用未初始化的指针,否则它们通常是未定义的。您需要确保在使用之前始终将您定义的任何指针初始化为有效的指针。

答案 2 :(得分:0)

1)您说构造函数中ll设置为NULL。但是什么构造函数?这里没有类定义。 ll是全局变量吗?你确定LLNode的构造函数将next指针设置为NULL吗?

2)条件

    if (ll == NULL)
可以而且应该在循环之外检查

,因为ll未在循环中修改

3)current是一个局部堆栈变量,因此一旦函数退出,赋值就不起作用。特别是,current = new LLNode(e)是内存泄漏。

4)要将节点添加到链接列表,您必须找到现有列表的最后一个节点,并修改其next指针。像这样的东西会起作用:

 // ll is a field representing the first node in your existing linked list.
 if (ll == NULL) {
     ll = new LLNode(e);
 }
 else {
     current = ll;
     while (current->next != NULL) {
         current = current->next;
     }
     current->next = new LLNode(e);
 }

编辑:根据您ll是班级成员的评论修改了上述内容。

答案 3 :(得分:0)

我在你的代码中看到的第一件事是当前是本地的,用新的分配,但实际上从未附加到列表。

当然你的代码应该是

else if( current->next == NULL )
{
   current->next = new LLNode( e );
   break;
}

LLNode当然必须在其构造函数中的NULL旁边初始化。

当然你的列表有O(N)插入时间,如果这不是练习,你几乎肯定会使用标准库容器。

你也应该将边缘情况移出循环。