关于c+中的链表/指针的问题+; C++中指针为空的性质似乎是任意的。我确信有一种方法是我遗漏的,但是下面的方法对我来说是有意义的,但似乎不起作用。我有以下将节点添加到链接列表的方法: 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; } } }

关于c+中的链表/指针的问题+; C++中指针为空的性质似乎是任意的。我确信有一种方法是我遗漏的,但是下面的方法对我来说是有意义的,但似乎不起作用。我有以下将节点添加到链接列表的方法: 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; } } },c++,pointers,C++,Pointers,将第二个节点添加到列表中时,不会捕捉到current==NULL的情况,因此它尝试调用current=current->next,并尝试访问无效内存。为什么会这样?LLNode有一个指向元素的指针,另一个LLNode旁边有一个被调用的指针。您可能没有在LLNode构造函数中将next指针设置为NULL C++中基本类型的对象(指针类型、数值类型等)具有不确定的初始值:默认情况下它们不会初始化。在使用这些对象之前,您需要显式地初始化它们。对于这种情况,您需要一个指向指针的指针,以便在实现中消除许

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

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


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

对于这种情况,您需要一个指向指针的指针,以便在实现中消除许多不必要的异常:

LLNode *ll = NULL;

void addToLL(Elem *e)
{
  LLNode** current = &ll;

  // 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中,这通常作为测试零操作来实现

指针仅在初始化为空时才为空。在C语言中,除非正确初始化,否则它们通常是未定义的,引用未初始化的指针会导致灾难。您需要确保您定义的任何指针在使用它们之前总是初始化为有效的值。

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
是类成员的评论修改了上述内容。

我在您的代码中看到的第一件事是current是本地的,分配了new,但从未实际附加到列表中

当然你的代码应该是

else if( current->next == NULL )
{
   current->next = new LLNode( e );
   break;
}
当然,LLNode必须在其构造函数中的NULL旁边初始化

当然,您的列表有O(N)个插入时间,如果这不是一个练习,那么您几乎肯定应该使用标准库容器


您可能还应该将边缘大小写移出循环。

您的插入逻辑不正确:您更改了
当前
指针,但从未更改任何节点的
下一个
指针以指向链接列表中的新元素。如前所述,列表中不能有多个节点。既然您说要在构造函数中将
ll
设置为NULL,那么它是类的成员吗?这个addToLL函数是一个类的方法吗?对不起,为了简单起见,我把它删掉了。ll和方法都是同一个类的成员。看起来你脑子里有JavaScript或类似的东西在使用
null
而不是
null
@tadman:谢谢,修复了。(java,更可能。但是当 null >代码>是C++中的约定时,我也看到了小写代码 null 。)使用指针指针工作,但我不认为它是“需要的”。我更喜欢避免双重间接寻址的解决方案,即使它们稍微复杂一些。分支的数量越少,实现中可能出现的逻辑故障的数量就越少,而且它简化了测试。在处理指针时,使用指针是完全合理的,就像在处理数据时使用指针是完全合理的一样。只差一层。