2010-01-31 78 views
0

我的C++有点生疏,但我制作了一个反转链接列表的程序,现在我正在尝试为它编写适当的析构函数,但我不知道要摧毁什么。这里是我的班级定义:C++析构函数示例

class LinkedList 
{ 
    private:ListElement *start; 
    public:LinkedList(); 
    public:void AddElement(int val); 
    public:void PrintList(); 
    public:void InvertList(); 
}; 

class ListElement 
{ 
    public:int value; 
    public:ListElement * link; 
    public:ListElement(int val); 
    public:ListElement(); 
}; 


class Stack 
{ 

private:ListElement ** stack; 
private:int index; 
public:Stack(int size); 
public:void push(ListElement * le); 
public:ListElement * pop(); 

}; 

该堆栈用于当我反转列表。 无论如何... 我将如何去写这些析构函数? 我在想:

对于ListElement使值0和链接0(NULL)。

对于LinkedList,检查元素并为它们调用ListElementDestructor。

我不是很确定这件事,因为据我所知,析构函数会自动调用成员对象的析构函数,所以在这种情况下只会为LinkedList写一个空的析构函数就足够了吗?我不知道...这就是为什么我要求

对于堆栈我不知道...在列表被反转后指针已经是0(NULL),因为它们全部都是poped。

我有点困惑。 任何人都可以帮忙吗? 预先感谢您。

+4

只是交换元素之间的指针方向而不是使用堆栈更容易吗? – Yacoby 2010-01-31 11:52:56

+4

重复私人和公共关键字是不必要的。只是做 私人: //私有变种声明 公共: //公共var声明 – batbrat 2010-01-31 11:56:22

+1

我还建议使listElement的“链接”成员专用,并提供一个只读的访问权限到下一个)方法 – davka 2010-01-31 12:32:24

回答

1

对于ListElement使值0,而链接0(NULL)。

您不需要重置析构函数中的任何值,因为执行析构函数后值不会存在。

您需要确定的主要事情是使用delete(或在数组情况下为delete [])删除在堆上分配的所有元素(即使用new)。

对于LinkedList,检查元素并调用它们中的所有ListElementDestructor。

对于在堆栈中分配的对象,当对象超出作用域时会自动调用该对象。
对于动态分配的对象(即使用new创建),当使用delete删除 时,调用析构函数。换句话说,如果您正确清理对象,则不需要调用任何析构函数,因为它们会自动调用。

假设你在LinkedList类的堆中分配新的ListElement,你应该确保在LinkedList析构函数中,每个ListElement在析构函数中被删除,方法是在列表中向下走,并在每个ListElement上调用delete (当然你已经从中检索了下一个列表元素的地址)。事情是这样的:

ListElement* current = list.start;  
while(current){ 
    ListElement* next = current->next; 
    delete current; 
    current = next; 
} 

没有什么在ListElement类需要清理,因为虽然它有一个指向下一个元素的缺失可能应该在LinkedList类来处理,这意味着它不需要一个析构函数。
不需要为每个类编写析构函数,因为编译器会自动为您生成一个空析构函数。

正如我在评论中所说的,你不应该使用堆栈来反转链表。你应该只是交换指针的方向。
大概是你想要的东西的一个简单例子。

ListElement* previous = 0; 
ListElement* current = list.start; 

while(current->next){ 
    //copy the address of current item on the list 
    ListElement* next = current->next; 

    //point the current list item to the previous list item 
    current->next = previous; 

    //set the current list item to the next list item 
    current = next; 

    //and the previous list item to the current one 
    previous = current; 
} 
//set the start of the list to what was the end 
list.start = current; 
+0

这是我学会在高中时学习的一种方式。如果你能告诉我如何扭转指针,我会非常感激。我不知道这可以通过其他方式完成。这只是我头上的第一件事。我接受任何其他解决方案。其实我会很感激。 – Para 2010-01-31 20:35:51

+0

@Para我编辑了我的帖子一些粗糙的(和未经测试的)通过交换指针来颠倒链接列表的代码。即使它不能100%正确工作,它也应该让你知道如何去做。 – Yacoby 2010-01-31 22:33:52

9

你摧毁了需要摧毁的东西。如果您的类使用new创建对象,那么您可能需要使用析构函数将析构函数删除。请注意像LinkedList这样的容器应该只包含动态分配的元素或不包含的元素。如果您混淆了这两者,或混合原件和副本,因为我怀疑您正在做这些事情,您可能需要使用智能指针或引用计数。其次,如果你确实需要反转一个单链表(30年编程中的某些事情,我从来不需要这样做),那么你只是简单地使用了错误的数据结构 - 你应该使用一个双向链表在这种情况下,不需要做任何事情。

第三,我可以说,你的C++风格是非惯用的,对我来说几乎是不可读的 - 使C++看起来像Java不是一个好主意。更改为:

class LinkedList 
{ 
    private: 
     ListElement *start; 
    public: 
     LinkedList(); 
     void AddElement(int val); 
     void PrintList(); 
     void InvertList(); 
}; 
+0

嗯......我实际上曾将此作为求职面试的一个问题:“编写适当的代码(包括类结构)以反转单个链表”。我强调“单链表”。我也在帕斯卡高中和爪哇大学学习过。对不起,让C++看起来像Java我真的不是故意的我想我已经习惯了这样写东西。 – Para 2010-01-31 20:32:55

1

LinkedList类创建ListElements。所以你需要循环从列表的开始到结尾(除非它是空的)。并且:

delete currentElement; 

在LinkedList析构函数中。由于ListElement将值存储为'int',因此您并不需要在此处释放内存。就像你想的那样。

同样,不需要释放Stack类的析构函数中的内存。一般来说,删除你新的东西!并让一个人(班级)负责这项工作!