我正在为练习创建链接列表,我遇到了问题。
我创建了两个相似的代码,在第一个代码中,我创建了某个structure called Node
作为variable
,在第二个代码中,我创建了一个structure called Node
作为pointer
在我看来,它应该以相同的方式工作,但事实并非如此。我将发布代码并查看名为addNode()
的函数。
我还有下一个问题:为什么我必须传递这样的指针:addNode( Node *& head, Node *& tail )
以使其正常工作,而不是将它们作为addNode( Node * head, Node * tail )
传递。
第一个代码(坏):
#include <iostream>
#include <string>
using namespace std;
struct Node{
int val;
Node * prev;
Node * next;
Node( int val ) : val( val ) { }
};
void printList( Node * ptr ){
while( ptr != NULL ){
cout << ptr -> val << " ";
ptr = ptr -> next;
}
cout << endl;
}
void addNode( int val, Node *& head, Node *& tail ){
Node tmp( val );
if( head == NULL ){
head = &tmp;
tail = &tmp;
tmp . prev = NULL;
tmp . next = NULL;
}
else{
tail -> next = &tmp;
tmp . prev = tail;
tmp . next = NULL;
tail = &tmp;
}
}
int main(){
Node * head = NULL;
Node * tail = NULL;
addNode( 3, head, tail );
addNode( 8, head, tail );
addNode( 2, head, tail );
addNode( 4, head, tail );
addNode( 15, head, tail );
addNode( 11, head, tail );
/*Node b( 5 );
cout << b . val << endl;
*/
printList( head );
return 0;
}
第二个代码(好):
#include <iostream>
#include <string>
using namespace std;
struct Node{
int val;
Node * prev;
Node * next;
Node( int val ) : val( val ) { }
};
void printList( Node * ptr ){
while( ptr != NULL ){
cout << ptr -> val << " ";
ptr = ptr -> next;
}
cout << endl;
}
void addNode( int val, Node *& head, Node *& tail ){
Node * tmp = new Node( val );
if( head == NULL ){
head = tmp;
tail = tmp;
tmp -> prev = NULL;
tmp -> next = NULL;
}
else{
tail -> next = tmp;
tmp -> prev = tail;
tmp -> next = NULL;
tail = tmp;
}
}
int main(){
Node * head = NULL;
Node * tail = NULL;
addNode( 3, head, tail );
addNode( 8, head, tail );
addNode( 2, head, tail );
addNode( 4, head, tail );
addNode( 15, head, tail );
addNode( 11, head, tail );
/*Node b( 5 );
cout << b . val << endl;
*/
printList( head );
return 0;
}
答案 0 :(得分:2)
如果执行Node tmp
,则在退出定义范围后,tmp
将被销毁。
另一方面,执行Node *tmp = new Node
为堆上的Node
分配内存并为其指定tmp
。 Node
只有在您拨打delete
时才会销毁。
进入问题的第二部分,如果需要修改指针而不是指针指向的对象,则需要通过引用传递指针。
如果您head = tmp, tail = tmp
没有通过引用传递head
和tail
,那么head
和tail
将仅保留此值,直到此函数的范围为止。此更改不会反映在addNode()
之外。
答案 1 :(得分:1)
为了使用函数修改head
和tail
,必须通过 reference ,即第二个代码段传递它们。
在第一个片段中,它们是通过 value 传递的,在函数addNode()
内完成的任何修改都将在函数超出范围后消失。
案例1 :按值传递
addNode(head); // call
功能体:
void addNode(Node *headCopy) { // Node *headCopy = head, copy is created
headCopy = &someThing; // the copy of head point to something else
// not the actual 'head' that changes its pointee
}
案例2 :通过引用传递
addNode(&head);
功能体:
void addNode(Node *&headReference) { // reference to 'head'
headReference = &someThing; // the actual 'head' changes its pointee
}
答案 2 :(得分:0)
由于原始指针的复制操作很便宜,所以没有理由通过引用传递它。
void addNode( int val, Node *& head, Node *& tail ){
Node tmp( val ); // tmp - local variable
if( head == NULL ){
head = &tmp; // address of local variable
tail = &tmp; // above
tmp . prev = NULL;
tmp . next = NULL;
}
else{
tail -> next = &tmp; // above
tmp . prev = tail;
tmp . next = NULL;
tail = &tmp; // above
}
} // local variable tmp get destructed, tail head contain address of unexisting object
它的双链表,并在Node构造函数中更改Node成员val或参数val的名称,添加head(nullptr),tail(nullptr),否则它不会为NULL