链接列表 - 新节点指针与新节点变量

时间:2016-03-18 10:48:01

标签: c++ struct linked-list

我正在为练习创建链接列表,我遇到了问题。

我创建了两个相似的代码,在第一个代码中,我创建了某个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;
}

3 个答案:

答案 0 :(得分:2)

如果执行Node tmp,则在退出定义范围后,tmp将被销毁。

另一方面,执行Node *tmp = new Node为堆上的Node分配内存并为其指定tmpNode只有在您拨打delete时才会销毁。

进入问题的第二部分,如果需要修改指针而不是指针指向的对象,则需要通过引用传递指针。

如果您head = tmp, tail = tmp没有通过引用传递headtail,那么headtail将仅保留此值,直到此函数的范围为止。此更改不会反映在addNode()之外。

答案 1 :(得分:1)

为了使用函数修改headtail,必须通过 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