【问题标题】:Modifying head pointer in a linked list修改链表中的头指针
【发布时间】:2011-10-12 05:27:19
【问题描述】:

我无法理解这段代码。我真正需要的是修改头指针以指向第一个元素。那么为什么 *head 不工作呢?更改 *head 的值会更改此指针指向的位置并且应该可以工作,对吗?我已经阅读了按引用传递/按值传递,但发现很难理解。有人可以帮助澄清这一点吗? 感谢你的帮助。谢谢。

在 C/C++ 中,指针误用更容易出错。考虑一下在列表前面插入元素的 C/C++ 代码:

bool insertInFront( IntElement *head, int data ){
  IntElement *newElem = new IntElement;
  if( !newElem ) return false;

  newElem->data = data;
  head = newElem; // Incorrect!
  return true;
}

前面的代码是不正确的,因为它只更新了头指针的本地副本。正确的版本传入一个指向头指针的指针:

bool insertInFront( IntElement **head, int data ){
  IntElement *newElem = new IntElement;
  if( !newElem ) return false;

  newElen->data = data;
  *head = newElem; // Correctly updates head
  return true;
}

【问题讨论】:

  • 我没有学过编程,但是如果IntElement 似乎没有专门用于链接元素的字段,它怎么是链表? =\
  • 是的,代码丢失 newElem->next = *head;

标签: c pointers linked-list


【解决方案1】:

您需要帮助来理解其中的区别,对吧?

想象一下第一种情况下函数的调用者:

IntElement *head;
int data;
...
insertInFront (head, data);

现在,在这种情况下,head 指向的地址被放置在堆栈中,并作为参数传递给 insertInFront。当 insertInFront 执行 head = newElement;只有参数(在堆栈上)被修改。

在第二种情况下,调用者是:

IntElement *head;
int data;
...
insertInFront (&head, data);

在这种情况下,head 的地址被放置在堆栈上并作为参数传递给 insertInFront。当你做 *head = newElement 时,这个传入的地址被取消引用以获得原始列表头的地址,并被修改。

【讨论】:

    【解决方案2】:

    当您了解指针是什么时,它相当简单。在第一个代码IntElement *head 中,head 是指向现有链表头的指针。所以调用者传入了列表头元素的地址。在 insert-in-front 函数中更改 head 的值不会改变调用者的任何内容。该地址的值已传递给您的函数 - 而不是将该地址保留给调用者的内容。

    您需要传递您的函数“头部地址的地址” - 或IntElement **head。这将允许此函数修改调用者持有的地址 - 即更新链表以指向新的头。

    【讨论】:

      【解决方案3】:

      你不想改变 head 指向的值,你想改变存储在 head 本身中的指针,所以不要使用 *head,使用指向 head 本身的指针。 head 是IntElement * 类型,所以参数应该是指向这种类型的指针:IntElement **

      【讨论】:

        【解决方案4】:

        当你在某处有一个值 T x 并且你想要一些其他函数来修改它时,你传递一个指向 x 的指针:

        T x;             // set to some value
        
        modify_me(&x);   // will change x
        
        /* ... */
        
        void modify_me(T * x)
        {
          *x = new_value;
        }
        

        现在只需将此机制应用于T = IntElement*。您要修改的值本身就是指针!

        (也许使用 typedef 会让事情看起来不那么混乱:typedef IntElement * NodePtr;。)

        还请注意,您的链表已损坏,因为您从未将新元素的“下一个”指针设置为指向旧的头,如果列表是双向链接的,则类似地设置“上一个”指针。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-19
          • 1970-01-01
          • 2015-08-25
          • 1970-01-01
          相关资源
          最近更新 更多