我很难理解这段代码。我真正需要做的就是修改头指针,让它指向第一个元素。那么为什么头脑不起作用呢?改变*头的值改变这个指针指向的地方,这应该工作,对吧?我已经按引用/按值传递过了,但我觉得很难理解。有人能帮我澄清一下吗?谢谢你的帮助。谢谢。
在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 *head;
int data;
...
insertInFront (head, data);
现在,在这种情况下,由head指向的地址被放在堆栈上,并作为参数传递给insertInFront。当insertInFront执行head = newElement;只有实参(在堆栈上)被修改。
在第二种情况下,调用者将是:IntElement *head;
int data;
...
insertInFront (&head, data);
在这种情况下,head的地址被放在堆栈上,并作为参数传递给insertInFront。当您执行*head = newElement时,传入的address将被取消引用,以获得原始列表头的地址,并对其进行修改。
当你了解指针是什么时,它是相当简单的。在第一个代码IntElement *head
中,head是指向链表的现有头部的指针。所以调用者传递的是列表头元素的地址。在insert-in-front函数中改变head的值不会改变调用者的任何东西。该地址的值被传递给你的函数——而不是在调用者那里保留该地址的东西。
你需要传递你的函数'头的地址的地址' -或IntElement **head
。这将允许此函数修改调用者持有的地址-即更新链表以指向新的头部。
你不想改变head指向的值,你想改变存储在head本身的指针,所以不要使用*head,使用指向head本身的指针。Head的类型是IntElement *
,所以参数应该是指向IntElement **
当你在某个地方有一个值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;
.)
还要注意,你的链表是坏的,因为你从来没有设置新元素的"next"指针指向旧的头,同样,如果列表是双链接的,"previous"指针也指向旧的头。