免费商店的双重链表

时间:2015-02-07 18:40:31

标签: c++ c++11 smart-pointers doubly-linked-list

我已经编程了大约8个月,所以我对编程很陌生,并且遇到了ADT,包括Doubly Linked List。

我意识到我看到的双重链接列表实现都没有在免费商店中,它们都在堆栈上。不会让免费存储上的每个节点都具有更高的内存效率,考虑到如果从列表中删除特定节点,您可以立即在所述节点上调用delete,而不是等待整个LinkedList结构超出范围?

至少如果我理解正确,只需使用正常的重新链接过程从列表中删除节点,实际上不会释放节点占用的内存。

我知道免费商店与关键字相关联,如果有新商品,则应遵循删除。我了解到,您实际上不应该使用原始指针来管理内存,因为如果您忘记删除免费商店中的项目,则会出现内存泄漏。幸运的是, C ++ 11引入了智能指针可以解决这个问题,但问题是,究竟谁是免费商店中链接列表结构中节点的所有者?

在一个非常基本的LinkedList中,我们可能有这个

struct Node
{
    int _value;
    Node * _next = nullptr;
    Node * _prev = nullptr;

    Node(int value) : _value(value) {}
};

class LinkedList
{
    Node * _head = nullptr;
    Node * _tail = nullptr;
    int _count = 0;

public:
    //ctors & dtor
    //getters & setters & other methods
};

其中 _count 是当前存储在链接列表中的元素数。考虑到不应该使用原始指针来管理内存,我想到了,我应该将一些原始指针转移到C ++ 11中引入的 库中的智能指针。

问题是, 1)我真的没看到,谁应该拥有在免费商店中创建的节点,即。我应该将哪些原始指针转换为智能指针?

2)另一个问题是, std :: unique_ptr 对于此实现是否足够?即使我使用 std :: unique_ptr ,一旦我从列表中取消链接,是否会删除一个节点?程序将如何知道,节点不再使用?

非常感谢您的回复。


编辑:作为参考,我正在添加两个方法,构造函数和我的实现的Insert方法。这就是我在堆栈上有一个LinkedList的意思。正如您所看到的,我没有在我的代码中的任何地方使用新的,但是,链接列表可以工作。

LinkedList(int value)
{
    Node newNode(value);

    _head = &newNode;
    _tail = &newNode;
    _count++;
}

void InsertAtEnd(int value)
{
    Node newNode(value);

    //tail points to nothing, list is empty
    if (_tail == nullptr)
    {
        _head = &newNode;
        _tail = &newNode;
        _count++;
    }
    //list is not empty
    else
    {
        _tail->_next = &newNode;
        _tail = &newNode;
        _count++;
    }
}

1 个答案:

答案 0 :(得分:1)

考虑实现一个智能指针:如果你盲目地遵循规则,你需要一个智能指针来实现一个智能指针。在这种情况下,您有一个例外。类似地,对于链接列表,节点之间的指针不代表所有权。相反,列表(class LinkedList)拥有所有节点,而在内部它们只是连接"。

为了所有这些的完整性并实施" A"在" ADT"中,需要隐藏这些实现细节。特别是,用户永远不应该直接访问节点。这也意味着列表和节点形成一个单元(通常存在C ++ friend关系),并且在内部它们使用原始指针(就像智能指针一样)。由于这是受到外部保护的,因此不使用原始指针的规则的例外是合理的。

注意:

  • 实施链接列表是一种很好的学习体验,但如果有std::list,请不要认真考虑使用它。
  • 关于所有权管理,我在LinkedList中使用std::deque<Node>成员来存储节点。在该容器内,您甚至可以维护已使用和未使用的元素的列表。是的,它有点作弊,但它使所有权管理安全(即没有内存泄漏),同时仍然为您提供构建链表的学习体验。
  • 请注意,您还可以在C ++中嵌套类。在这种情况下,我将节点类嵌套在链表类中。毕竟,在链表类之外不应该需要该类,因此它也不必在同一名称空间中。