2
#pragma once // Link.h

#include <memory>
template <typename E>
class Link
{
private:
    static Link<E> * freelist; // Pointer to the freelist head
                              // How to release the memory??

public:
    E element;
    Link *next;

    Link(const E &eleval, Link *nextval = nullptr)
        : element(eleval)
        , next(nextval) {}
    Link(Link *nextval = nullptr) : next(nextval) {}

    /*~Link()
    {
        while (freelist->next != nullptr)
        {
            Link<E> *tmp = freelist;
            freelist = freelist->next;
            delete tmp;
        }
    }
*/
    void *operator new(size_t)
    {
        if (freelist == nullptr) return ::new Link;
        Link<E>* temp = freelist;
        freelist = freelist->next;
        return temp;
    }

    void operator delete(void* ptr)
    {
        ((Link<E>*)ptr)->next = freelist;
        freelist = (Link<E>*)ptr;
    }
};

template <typename E>
Link<E>* Link<E>::freelist = nullptr;

Link 类中有一个静态指针,旨在将 freelist 存储在我的链表中,我想在程序结束后释放这个 freelist 的内存。如何删除此 freelist 的内存。

PS:我试图像这样释放内存:

/*~Link()
    {
        while (freelist->next != nullptr)
        {
            Link<E> *tmp = freelist;
            freelist = freelist->next;
            delete tmp;
        }
    }
*/

但程序无故终止。

4

1 回答 1

1

但程序无故终止。

让我们看看那个循环。在这里您删除该项目:

delete freelist;

然后,在您删除它之后,您可以在循环条件中访问它:

while (freelist->next != nullptr)

那是未定义的行为。您正在访问已删除的元素。我建议改为进行递归,遍历列表并在退出时删除元素。也许像

/** Delete a link and all the ones after it as well */
void recursiveDelete()
{
    if (next){
        next->recursiveDelete();
    }
    delete this;
}

然后调用它freelist。此外,您需要删除以下重载:

void operator delete(void* ptr)
    {
        ((Link<E>*)ptr)->next = freelist;
        freelist = (Link<E>*)ptr;
    }

因此,如果我理解这一点,当您删除 a 时Link,您设置next了链接的 (无论如何都将被删除,所以什么都不做),然后您设置freelist该链接现在将变得无效。这会弄乱删除项目。

正如 Christophe 指出的那样,删除这样的大列表可能会导致堆栈溢出。可以通过使用不使用递归的算法来避免这种情况。你可以尝试这样的事情:

/** Delete a link and all the ones after it as well */
void deleteAll()
{
    std::vector<Link*> links;
    Link* toDelete = this;
    while (toDelete) {
        links.push_back(toDelete);
        toDelete = toDelete->next;
    }
    for (Link* i : links) {
        delete i;
    }
}
于 2018-10-10T06:31:40.400 回答