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

标签 c++ list destructor

这是对我今天早些时候提出的关于直接调用类的析构函数的拨款的问题的跟进。

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

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

我让 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;
}

这是我重载的输出流:

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;
}

看这个使用后的命令提示符窗口下面还打印了“Destructor called”。

列表析构函数:

List::~List()
{
    cout << "Destructor called" << endl;
//  List::Destroy();
}

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

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
}

我也有一个 List 的析构函数,当它被调用时写上“Destructor called”,并注意到它在每次使用其中一种方法后都会被调用。

这是为什么?我假设当对象不再需要时调用析构函数,即删除。

此外,在单步执行我的代码时,我注意到当指针被删除时,它指向的内存地址并没有被取消。删除后是否必须手动将指针置空?

最佳答案

这是因为您按值获取了您的列表——也就是说,您复制了它。你需要通过 const 引用来获取它——也就是说,

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

此外,您的赋值运算符应该采用常量引用,而不是非常量引用。

我也不认为这是

delete _head, _tail, _current, _del;

做你想做的事。它只是删除 _del而其他人都没有。

您应该使用递归的 self 拥有设计,其中每个节点都会删除链中的下一个节点。编辑:由于不清楚,我将发布一个简短的示例。

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.
    }
};

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

我建议您仔细阅读 std::auto_ptr ,它的接口(interface)有一些惊喜,例如“复制”构造函数和赋值运算符实际移动,您在使用该类之前会想知道这些。我希望我可以开始使用 std::unique_ptr而不是所有时间,这会让生活变得更加轻松。

关于每次使用 List 的方法后调用 C++ List 析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5051340/

相关文章:

python - 当存在重复项时,如何将两个元素列表转换为字典(一个元素将是键,另一个将是值)?

python - 读取文件并返回国家列表的方法

c++ - 析构函数和链表

c++ - 删除 NULL 指针在写入析构函数时不会调用重载删除

C++ 将函数应用于容器中的某些元素

c++ - boost::remove_if 导致错误(只读变量不可赋值)

c++ - 我必须检查什么接口(interface)来检测连接的 USB?

c++ - CUDA:减少变形和 volatile 关键字

r - 将用户定义的函数应用于数据框列表

python - 如何将上下文管理器用于实例变量