1

我正在试验一个链表。我的函数“null”似乎修改了我的列表,即使列表不是通过引用传递的。我已经读到,这些问题可能发生在作为普通按值调用参数传递的对象上,这也是类中的数据未在良好的 OOP 中声明为公共成员的原因之一。我已经尝试将 null 函数作为列表的成员函数,它工作正常,但我仍然想了解为什么这种方式不能正常工作。谢谢

#include <iostream>
#include <new>
#include <time.h>
#include <stdlib.h>
using namespace std;

class list{
    public:
    struct element {
    int data;
    element* next;
};

element * head;


list(){
    head=NULL;
}

~list(){
while (head!=NULL){
    element *e = head->next;
    delete head;
    head = e;
    }
    cout<<"Destructing..\n";
}

void add (int value){
    element *e = new element;
    e->data = value;
    e->next = head;
    head= e;
    }
};

void fill10 (class list & l){
    for (int i= 0; i<10 ;i++){
    l.add((rand()%10)+1);
    }
}

bool null (class list l){
    if (l.head!=NULL){ return false;}
    return true;
}


int main ()
{
    srand(time(NULL));
    class list l;
    fill10(l);

    cout<<l.head->data<<endl;
    cout<<l.head<<endl;

    cout<<endl<<null(l)<<endl;//when I comment this everything works out as expected

    cout<<l.head->data<<endl; //this data is not the same anymore after null is called
    cout<<l.head<<endl;

   return 0;
}
4

3 回答 3

2

问题是您将参数传递给null函数的方式

bool null (class list l){
    if (l.head!=NULL){ return false;}
    return true;
}

按值传递时,您会创建链接列表的副本。此副本将包含head与原始指针相同的副本。

当函数返回时,参数会被销毁,其析构函数会删除所有原始和副本共享的节点。

您要么必须通过引用传递,要么定义一个复制构造函数,为复制的列表创建新节点。

于 2012-06-28T13:04:48.573 回答
0

你的null函数需要一个list值,但是list? 它实际上只是一个指向实际内容的指针(the element)。因此,当您按值调用时,最终被复制的不是stuff (the element),而是指向 stuff的指针。

这就是它起作用的原因,就像你现在拥有的那样。

于 2012-06-28T13:01:34.363 回答
0

当您通过l值传递给null您调用复制构造函数和head副本将指向相同headl. 当此副本在 末尾超出范围时null,将head被删除,这与.head使用的相同l

在 C++ 中有一种叫做“三规则”的东西,它指出,无论何时定义析构函数、复制构造函数或赋值,都应该定义所有这些。

于 2012-06-28T13:02:29.577 回答