c++ - 如何防止广义链表内存泄漏?

标签 c++ pointers memory memory-leaks linked-list

我已经实现了自己的链表数据结构。数据存储在Node里面结构。代码如下

// NODE

template <typename T>
struct Node
{
    T data;
    Node<T> *next;
    Node(T);
};

template <typename T>
Node<T>::Node(T d) : data(d), next(NULL) {}
// LIST

#include "node.cpp"

template <typename T>
class List
{
    Node<T> *head;
    int size;

public:
    List();                       // Default constructor
    List(const List &);           // Copy constructor
    void push_back(const T &);    // Insert element to the end of the list
    int get_size() const;         // Get the current size of the list
    T &operator[](int) const;     // Overload [] operator
    void operator=(const List &); // Overload = operator
    ~List();                      // Destructor
};

template <typename T>
List<T>::List() : head(NULL), size(0) {}

template <typename T>
List<T>::List(const List &list) : head(NULL), size(0)
{
    for (int i = 0; i < list.size; i++)
        push_back(list[i]);
}

template <typename T>
void List<T>::push_back(const T &data)
{
    // Create new Node with data
    Node<T> *nn = new Node<T>(data);

    // Find insert position
    if (head == NULL)
    {
        head = nn;
        size++;
        return;
    }

    Node<T> *traverse = head;
    while (traverse->next)
        traverse = traverse->next;

    // Traverse points to end of the list
    traverse->next = nn;
    size++;
}

template <typename T>
int List<T>::get_size() const
{
    return size;
}

template <typename T>
T &List<T>::operator[](int index) const
{
    int count = 0;
    Node<T> *traverse = head;
    while (traverse && count < index)
    {
        traverse = traverse->next;
        count++;
    }
    return traverse->data;
}

template <typename T>
void List<T>::operator=(const List<T> &list)
{
    Node<T> *traverse = head;

    while (head)
    {
        traverse = head;
        head = head->next;
        delete traverse;
    }

    size = 0;
    for (int i = 0; i < list.getSize(); i++)
        push_back(list[i]);
}

template <typename T>
List<T>::~List()
{
    Node<T> *traverse = head;

    while (head)
    {
        traverse = head;
        head = head->next;
        delete traverse;
    }
}

问题在于内存泄漏。考虑以下main文件

#include "list.cpp"

using namespace std;

List<int *> l;

void func()
{
    int *i = new int[2];
    i[0] = 1;
    i[1] = 2;
    l.push_back(i);
}

int main()
{
    func();
    return 0;
}

根据 Valgrind 的说法,该程序存在内存泄漏。正是因为Node没有析构函数,因此无法删除 data在里面。但是,我无法将析构函数添加到 Node因为,假设我正在使用 List<int>所以删除不是动态分配的东西是错误的。简而言之,每当我使用 List 动态分配的数据类型时,我出现内存泄漏。我怎样才能克服这种情况?谢谢。

最佳答案

您示例中的泄漏与列表无关。你泄漏同样的:

void func()
{
    int *i = new int[2];
    i[0] = 1;
    i[1] = 2;
}

你必须delete您通过 new 创建的内容和delete[]您通过 new[] 创建的内容。修复泄漏:

void func()
{
    int *i = new int[2];
    i[0] = 1;
    i[1] = 2;
    l.push_back(i);
    delete [] i;
}

但是,请注意,然后在delete[]之后列表中有一个悬空指针。

这不是 List当您将原始指针推送到对象时,它会删除对象。列表无法知道它们是否拥有指针。例如:

void func()
{
    int i = 0;
    l.push_back(&i);
}

无需删除此处的任何内容。 (不过,这里也是一样:函数返回后,列表中就会有一个悬空指针)

以上两者都不是真正的“好”。不要使用原始拥有指针!请改用智能指针。如果你想要一个整数列表,那么使用 List<int> (或者更确切地说是 std::list<int> )。

关于c++ - 如何防止广义链表内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61840685/

相关文章:

c++ - 运算符的初始化列表和 RHS

C++ 无法从 vector 访问对象

c - 如何节省数组中未使用的空间?

c++ - 具有默认行为的函数指针

c++ - 动态分配的正确用法是什么——应该避免这种情况吗? (在不同的范围内使用 new 和 delete)

c - 如何使用指针仅指向数组的一半

c - 如何在 C 结构体中索引指针

java - 处理 Hadoop 中 reduce 步骤的大输出值

python - Python 内存优化是如何工作的?

c++ - QTreeView 禁用悬停在行上的突出显示