我正在学习智能指针,还有什么比在堆上实现简单结构(如链表)更好的了。

我创建了一个链接列表结构,如下所示...

// linked list node definition
#ifndef __LINKED_LIST_NODE_H
#define __LINKED_LIST_NODE_H

class LinkedListNode {
    friend class LinkedList;
public:
    int                 m_value;
    LinkedListNode *    m_pNext;
public:
    LinkedListNode();
    LinkedListNode(int);
    LinkedListNode(const LinkedListNode &);
    ~LinkedListNode();
};

#endif

// linked list definition
#ifndef __LINKED_LIST_H
#define __LINKED_LIST_H

class LinkedList {
    LinkedListNode * m_pHead;
    LinkedListNode * m_pTail;
public:
    LinkedList();
    LinkedList(int);
    LinkedList(const LinkedList &);
    ~LinkedList();
    void PrintList() const;
    void AddItem(int);
    void RemoveItem(int);
    LinkedListNode * FindNode(int) const;
    LinkedListNode * FindMin() const;
    LinkedListNode * FindMax() const;
};

#endif

这是LinkedListNode和LinkedList类的必需方法(构造函数和析构函数),以查看其外观(IIRC这些应该正确)...
// list node
LinkedListNode::LinkedListNode()
{
    m_value = 0;
    m_pNext = nullptr;
}

LinkedListNode::LinkedListNode(int value)
{
    m_value = value;
    m_pNext = nullptr;
}

LinkedListNode::LinkedListNode(const LinkedListNode & copyNode)
{
    m_value = copyNode.m_value;
    m_pNext = copyNode.m_pNext;
}

LinkedListNode::~LinkedListNode()
{
    // not needed, no dynamic allocation
}


// linked list
LinkedList::LinkedList()
{
    m_pHead = nullptr;
    m_pTail = m_pHead;
}

LinkedList::LinkedList(int value)
{
    std::shared_ptr<LinkedListNode>newNode{ new LinkedListNode(value) };
    m_pHead = newNode.get();
    m_pHead->m_pNext = nullptr;
    m_pTail = m_pHead;
}

LinkedList::LinkedList(const LinkedList & copyList)
{
    if (copyList.m_pHead == nullptr)
    {
        m_pHead = nullptr;
        m_pTail = m_pHead;
    }
    else
    {
        std::shared_ptr<LinkedListNode>NodeResource{ new LinkedListNode(*copyList.m_pHead) };

        LinkedListNode * tempNode = NodeResource.get();

        m_pHead = tempNode;

        while (tempNode->m_pNext != nullptr)
        {
            std::shared_ptr<LinkedListNode>NodeResourceNext{ new LinkedListNode(*tempNode->m_pNext) };
            tempNode->m_pNext = NodeResourceNext.get();
            tempNode = NodeResourceNext.get();
        }

        m_pTail = tempNode;
    }
}

LinkedList::~LinkedList()
{
    // not needed, allocating using smart pointers
}

现在,LinkedList类包含AddItem方法,其主体为:
void LinkedList::AddItem(int value)
{
    std::shared_ptr<LinkedListNode>newNode{ new LinkedListNode(value) };

    if (m_pHead == nullptr) // linked list is empty
    {
        m_pHead = newNode.get();
        m_pTail = newNode.get();
    }
    else
    {
        m_pTail->m_pNext = newNode.get();
        m_pTail = newNode.get();
    }
}

而且我不知道为什么,但是当我尝试向链接列表中添加项目时,当您超出方法范围时,似乎newNode变量将被删除。

这是我尝试调试程序时的样子...

首先,我们从一个空的链接列表开始

然后在AddItem函数中,我得到以下结果(看起来m_pHead和m_pTail正确地指向堆上新创建的newNode。

但是当AddItem()方法超出范围时,这就是我剩下的

我以为,一旦没有引用指针,std::share_ptr将被删除。在我的情况下,newNode被两个指针m_pHead和m_pTail引用。离开AddItem()方法后,它真的被删除了吗?还是我的代码中没有发现一个缺陷?

伙计们,非常感谢您的投入。

最佳答案

您正在将newNode.get()分配给LinkedListNode*的原始指针(LinkedListNode)成员。

这是不正确的,因为shared_ptr(至少在这种情况下)拥有底层指针。当超出范围时,关联的内存将被释放,但是您的LinkedListNode仍然具有以前分配的内存的成员。

您可能应该更改LinkedListNode的定义,以使其LinkedListNode*成员改为shared_ptr<LinkedListNode>,以确保只要实例存在就可以引用基础内存。

10-05 21:15