C ++中List类的析构函数

问题描述 投票:-1回答:2

我是C ++的新手,因此这个问题。我在C ++中有一个单一链接列表的玩具实现。

template<typename T>
class List {
    template<typename U>
    struct Node {
        U data_;
        Node<U>* next_;

        Node() : data_(0), next_(nullptr) {}
        Node(U data) : data_(data), next_(nullptr) {}
    };

private:
    Node<T>* head_;
    std::size_t size_;

public:
    List() : head_{nullptr}, size_{0} {}

    void insert(const T& item) {
        Node<T>* p(new Node<T>(item));
        if (size_ == 0) {
            head_ = p;
        } else {
            p->next_ = head_;
            head_ = p;
        }
        size_++;
    }
    std::size_t getSize() {
        return size_;
    }

    ~List(){
    while(head_){
        Node<T> p = head_;
        delete(p);
        head_ = head_->next_;
    }
};

这段代码似乎有效。但问题是new分配的对象永远不会被清除,尽管有~List()析构函数。有人可以帮助我理解,我怎么能为这个类编写一个析构函数来清理所有分配的节点?

重要说明:我知道这可以使用智能指针来完成,但我想了解旧学校管理堆栈的方法。

c++ memory-management containers singly-linked-list object-lifetime
2个回答
7
投票
while(head_){
    Node<T> p = head_; <-- change to pointer
    delete(p); <-- you can't delete this right now
    head_ = head_->next_;
}

p应该是一个指针。你不能马上删除p。你必须找到next节点,然后删除p。也使用delete p;而不是delete (p);如下:

~List() {
    while(head_) {
        Node<T> *p = head_;
        head_ = head_->next_;
        delete p;
    }
}

如评论中所述,Node不需要是模板。你可以简化你的课程。 insert也可以简化,因为head_初始化为nullptr,你可以安全地分配p->next_ = head_;

template<typename T> class List {
    struct Node {
        T data_;
        Node* next_;
        Node() : data_(0), next_(nullptr) {}
        Node(T data) : data_(data), next_(nullptr) {}
    };
    Node* head_;
    std::size_t size_;
public:
    List() : head_{ nullptr }, size_{ 0 } {}

    void insert(const T& item) {
        Node* p = new Node(item);
        p->next_ = head_;
        head_ = p;
        size_++;
    }

    std::size_t getSize() {
        return size_;
    }

    ~List() {
        while(head_) {
            Node *marked = head_;
            head_ = head_->next_;
            delete marked;
        }
    }
};

-1
投票

一般的想法是你必须弄清楚谁是对象的所有者,以决定谁应该删除它。

对于节点,List是所有者。因此,您应该以一种方式仔细开发所有方法,一旦List失去对象的所有权,它就会确保删除对象或接管所有权。

想要释放内存的明显地方是,首先删除列表。其次,当你删除一个元素时,例如弹出它。

让我们看看两种情况。

首先删除列表。为此你需要编写一个析构函数,它遍历列表并逐个删除元素。为此我指的是@ barmak-shemiani的答案。

对于弹出元素的情况,您可以执行以下操作:

  T pop() {
    Node<T> *tmp = head_;
    if (head_ != nullptr)
      head_ = head_->next_;
    T data = tmp->data_;
    delete tmp;
    return data;
  }
© www.soinside.com 2019 - 2024. All rights reserved.