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

时间:2014-04-12 16:06:48

标签: c++ c++11 shared-ptr smart-pointers

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

但我似乎无法找到正确的方法。

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

我遇到的问题是破坏整个清单,

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

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

遵循以下代码:

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;
    };

linkedlist.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);
    }

Node.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,

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

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

1 个答案:

答案 0 :(得分:3)

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

i99开头并且您只添加它(++i)时,可能会在溢出之前发生错误。你可能意味着--i

你应该考虑这样写:

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

或者:

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

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


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