C++11在双链表中正确使用智能指针

C++11 Correct usage of smart pointers in a doubly linked list

本文关键字:智能 指针 链表 C++11      更新时间:2023-10-16

我正在尝试使用一些新的设计技术来实现链表

但我似乎想不出正确的方法。

技术是智能指针和空对象模式。

我遇到的问题是整个名单的销毁,

我有一个实现,它没有破坏一些对象,

现在我似乎有一个循环问题,它根本不存在。

遵循代码:

linkedlist.h

    #pragma once
    #include <memory>
    #include "node.h"
    class LinkedList {
    public:
        LinkedList() : m_size(0), head(nullptr) {};
        void addNode(int value);
        void removeNode(int index);
    private:
        std::shared_ptr<Node> getNodeAtIndex(int index);
        std::shared_ptr<Node> getLastNode();
        void _addNode(int value);
        inline void increaseSize() { ++m_size; }
        inline void decreaseSize() { --m_size; }
    private:
        size_t m_size;
        std::shared_ptr<Node> head;
    };

链接列表.cpp

    #include "linkedlist.h"
    void LinkedList::addNode(int value) {
        _addNode(value);
        increaseSize();
    }
    void LinkedList::_addNode(int value) {
        if (nullptr == head) {
            head = std::make_shared<Node>(Node(value));
            return;
        }
        std::shared_ptr<Node> tail = getLastNode();
        std::shared_ptr<Node> nextNode = std::make_shared<Node>(Node(value));
        nextNode->setPrevious(tail);
        tail->setNext(nextNode);
    }
    void LinkedList::removeNode(int index) {
        std::shared_ptr<Node> node = getNodeAtIndex(index);
        node->getNext()->setPrevious(node->getPrevious());
        node->getPrevious()->setNext(node->getNext());
        decreaseSize();
    }
    std::shared_ptr<Node> LinkedList::getNodeAtIndex(int index) {
        std::shared_ptr<Node> node = head;
        for (int i = 0; i < index; ++i) {
            node = node->getNext();
        }
        return node;
    }
    std::shared_ptr<Node> LinkedList::getLastNode() {
        return getNodeAtIndex(m_size-1);
    }

节点.h

    #pragma once
    #include <memory>
    class Node {
    public:
        Node() : value(0), next(nullptr), previous(nullptr) {};
        Node(int value) : value(value) {};
        ~Node() { printf("%d", value); };
        std::shared_ptr<Node> getNext();
        virtual void setNext(std::shared_ptr<Node> newNext);
        std::shared_ptr<Node> getPrevious();
        virtual void setPrevious(std::shared_ptr<Node> newPrevious);
    private:
        int value;
        std::shared_ptr<Node> next;
        std::shared_ptr<Node> previous;
    };
    class NullNode : public Node {
    public:
        virtual void setNext(Node* newNext) {};
        virtual void setPrevious(Node* newPrevious) {};
    };

node.cpp

    #include "node.h"
    std::shared_ptr<Node> Node::getNext() {
        if (nullptr == next) {
            return std::shared_ptr<Node>(new NullNode);
        }
        return next;
    }
    void Node::setNext(std::shared_ptr<Node> newNext) {
        next = newNext;
    }
    std::shared_ptr<Node> Node::getPrevious() {
        if (nullptr == previous) {
            return std::shared_ptr<Node>(new NullNode);
        }
        return previous;
    }
    void Node::setPrevious(std::shared_ptr<Node> newPrevious) {
        previous = newPrevious;
    }

main.cpp

    #include "linkedlist.h"
    void addToList() {
        LinkedList list;
        for (int i = 0; i < 100; ++i) {
            list.addNode(i);
        }
        for (int i = 99; i >= 0; ++i) {
            list.removeNode(i);
        }
    }
    int main() {
        addToList();
    }

我想知道我哪里出了问题——是因为shared_ptr、的返回吗

它是针对弱/唯一的sharedptr的选择吗?

当然,我该如何使这个代码示例正常工作。

for (int i = 99; i >= 0; ++i) {
    list.removeNode(i);
}

i一开始是99,而您只添加到它(++i)时,在它溢出之前可能会发生不好的事情。你可能是指--i

你应该考虑这样写:

for (int i = 0; i < 100; ++i) {
    list.removeNode(0);
}

或者:

while (!list.empty()) list.removeNode(0);

最后一种方法要求您公开容器的大小,或者添加requisite empty()函数来测试列表是否为空。


如果你在调试器中运行程序,它会帮助你自己发现这个问题。您应该学习如何使用调试器:)