简体   繁体   English

关于C ++中的链表/指针的问题

[英]Question about linked lists/pointers in c++

The nature of pointers being NULL in C++ seems to feel arbitrary. 指针在C ++中为NULL的性质似乎让人感到任意。 I'm sure there's a method to it that I'm missing, but the following makes sense to me, but doesn't seem to work. 我敢肯定有一种方法我不见了,但是以下内容对我来说很有意义,但似乎不起作用。 I have the following method for adding a node to a linked list: 我有以下将节点添加到链表的方法:

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

    }
}

When adding a 2nd node to the list, the case for current == NULL does not get caught, so it tries to call current = current->next and crashes do to accessing invalid memory. 将第二个节点添加到列表中时, current == NULL情况不会被捕获,因此它将尝试调用current = current->next并且崩溃会导致访问无效内存。 Why would this be the case? 为什么会这样呢? A LLNode has a pointer to an Elem, and a pointer called next to another LLNode. 一个LLNode有一个指向Elem的指针,以及另一个LLNode旁边的指针。

You probably didn't set the next pointer to NULL in the LLNode constructor. 您可能没有在LLNode构造函数中将next指针设置为NULL

Objects of the basic types in C++ (pointer types, numeric types, etc.) have indeterminate initial values: they don't get initialized by default. C ++中基本类型的对象(指针类型,数字类型等)具有不确定的初始值:默认情况下不会初始化它们。 You need to explicitly initialize such objects before you use them. 您需要在使用此类对象之前显式初始化它们。

For this sort of thing you need a pointer to a pointer in order to strip away a lot of the needless exceptions in your implementation: 对于这种事情,您需要一个指向指针的指针,以消除实现中的许多不必要的异常:

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

The reason pointers are NULL is because that evaluates to false and allows you to do simple checks such as while (*current) without a lot of overhead. 指针为NULL的原因是因为它的计算结果为false,并允许您进行诸如while (*current)类的简单检查while (*current)没有很多开销。 In the CPU this usually ends up being implemented as a test-if-zero operation. 在CPU中,这通常最终被实现为零测试操作。

Pointers are only NULL if initialized as such. 指针只有在初始化时才为NULL。 In C they are often undefined unless properly initialized and referencing an uninitialized pointer is recipe for disaster. 在C语言中,除非正确初始化它们,否则它们通常是未定义的,并且引用未初始化的指针会导致灾难。 You'll want to ensure any pointers you define are always initialized to something valid before using them. 您将要确保在使用它们之前,始终将定义的指针初始化为有效的指针。

1) You say that ll is set to NULL in the constructor. 1)您说ll在构造函数中设置为NULL。 But what constructor? 但是什么构造函数? There's no class definition here. 这里没有类定义。 Is ll a global variable? ll是全局变量吗? And are you sure that the constructor for LLNode sets the next pointer to NULL? 并且您确定LLNode的构造函数将next指针设置为NULL吗?

2) The condition 2)条件

    if (ll == NULL)

can and should be checked outside of the loop, as ll is not modified inside the loop. 可以并且应该在循环外部检查,因为ll在循环内部没有修改。

3) current is a local stack variable, so assigning to it will have no effect once the function exits. 3) current是一个局部堆栈变量,因此一旦函数退出,对其赋值将无效。 In particular, current = new LLNode(e) is a memory leak. 特别地, current = new LLNode(e)是内存泄漏。

4) To add a node to the linked list, you must find the last node of the existing list, and modify its next pointer. 4)要将节点添加到链接列表,必须找到现有列表的最后一个节点,并修改其next指针。 Something like this would work: 像这样的东西会起作用:

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

EDIT : Modified the above based on your comment that ll is a class member. 编辑 :根据您的评论修改了上述内容,即ll是课程成员。

The first thing I see in your code is that current is local, gets allocated with new but is never actually attached to the list. 我在您的代码中看到的第一件事是current是本地的,使用new分配,但实际上从未附加到列表中。

Surely your code should be 当然,您的代码应该是

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

LLNode must of course initialise next to NULL in its constructor. LLNode当然必须在其构造函数中的NULL旁边初始化。

Of course your list has O(N) insertion time, and if this is anything other than an exercise you should be almost certainly be using standard library containers. 当然,您的列表具有O(N)插入时间,如果这不是练习,则几乎可以肯定使用标准库容器。

You should also probably move the edge case out of the loop. 您可能还应该将边缘盒移出循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM