每次使用List的方法后调用的C++ List析构函数

Lee*_*Lee 1 c++ destructor list

这是我今天早些时候提出的关于直接调用类的析构函数的问题的后续问题.

我正在为作业创建自己的列表.我已经重载了赋值,方括号,输入和输出流操作符,并具有基本的添加,删除和打印到屏幕功能.

我的下一步是让List删除并释放其所有节点的内存,我遇到了麻烦.

我让List在执行操作后写入屏幕当前状态,如下所示:

void main()
{
    // Create instance of list
    List aList(true);
    List bList(true);
    aList.Add(1);
    aList.Add(2);
    bList.Add(2);
    cout << "aList: " << aList;
    cout << "bList: " << bList;
    aList = bList;
    cout << "aList: " << aList;
    cout << "bList: " << bList;
    aList.Add(3);
    cout << "aList: " << aList;
    cout << "bList: " << bList;
    int i = 0; cin >> i;
}
Run Code Online (Sandbox Code Playgroud)

这是我的重载流:

ostream &operator<<(ostream &stream, List theList)
{
    stream << "There are " << theList._totalNodes << " nodes in the list." << endl;
    for(int i = 0; i < theList._totalNodes; i++)
    {
        stream << "Node #" << i << " holds the data: " << theList[i] << endl;
    }
    return stream;
}
Run Code Online (Sandbox Code Playgroud)

在使用此命令提示符窗口之后,还会在其下方打印"Destructor called".

List析构函数:

List::~List()
{
    cout << "Destructor called" << endl;
//  List::Destroy();
}
Run Code Online (Sandbox Code Playgroud)

重载赋值运算符似乎也调用了析构函数,这并不让我感到惊讶.但是,其他人呢.

List &List::operator=(List &aList)
{
    // Make sure not the same object trying to be copied
    if(this != &aList)
    {
        // Perform deep copy
        // Delete old pointers in redundant list, only if they exist already
        if(_head)
        {
            delete _head, _tail, _current, _del;
            _totalNodes = 0; // Reset total nodes
        }
        // Now set new pointers copied from other list
        _head = NULL;
        _tail = _head;
        _current = _head;
        _del = _head;
        // Now loop through all nodes in other list and copy them to this
        // Reset pointer in other list
        aList.Reset();
        for(int i = 0; i < aList._totalNodes; i++)
        {
            Add(aList.Current()->_data);
            aList.Next();
        }
        // Reset other list's pointer
        aList.Reset();
        Reset(); // Reset our pointer
    }
    return *this; // Return for multi assignment
}
Run Code Online (Sandbox Code Playgroud)

我也有一个List的析构函数,当它被调用时写入"Destructor called",并注意到它在每次使用其中一个方法后被调用.

为什么是这样?我假设在不再需要对象(即删除)时调用析构函数.

此外,当我单步执行代码时,我注意到当删除指针时,它指向的内存地址不会被取消.删除指针后是否必须手动对其进行NULL操作?

Pup*_*ppy 5

这是因为你按照值获取了List,也就是说,你复制了它.你需要通过const引用来接受它 - 也就是说,

ostream &operator<<(ostream &stream, const List& theList)

此外,赋值运算符应采用const引用,而不是非const引用.

我也不认为这个

delete _head, _tail, _current, _del;

做你认为它做的.它只是删除_del而没有其他人.

您应该使用递归自拥设计,其中每个节点删除链中的下一个节点.编辑:由于目前还不清楚,我将发布一个简短的样本.

template<typename T> struct Node {
    Node(const T& arg, Node* prev) : t(arg), previous(prev) {}
    T t;
    std::auto_ptr<Node<T>> next;
    Node<T>* previous;
};
template<typename T> class List {
    std::auto_ptr<Node<T>> head;
    Node<T>* tail;
public:
    List() : head(NULL), tail(NULL) {}
    void clear() { head = tail = NULL; } // Notice how simple this is
    void push_back() {
        push_back(T());
    }
    void push_back(const T& t) {
        if (tail) {
            tail = (tail->next = new Node<T>(t, tail)).get();
            return;
        }
        tail = (head = new Node<T>(t, NULL)).get();
    }
    void pop_back() {
        tail = tail->previous;
        tail->next = NULL;
    }
    void pop_front() {
        head = head->next;
    }
    List<T>& operator=(const List& ref) {
        clear(); // Clear the existing list
        // Copy. Gonna leave this part to you.
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意我从未删除任何std::auto_ptr内容 - 为我做了一切,并且操作列表并且它的节点变得更加容易,因为std::auto_ptr管理所涉及的所有内存.此列表甚至不需要自定义析构函数.

我建议你仔细阅读std::auto_ptr,它的界面有一些惊喜,比如"复制"构造函数和赋值操作符实际移动,你在使用该类之前想要了解它.我希望我可以开始使用std::unique_ptr所有的时间,这将使生活变得更加容易.