jeudi 22 janvier 2015

Should referenced std::shared_ptr be deleted after method goes out of scope?

I am learning smart pointers and what is better to learn it than to implement a simple structure, such as Linked List, on the heap.


I created a linked list structure as follows...



// 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


Here are necessarry methods (constructors and destructors) for both LinkedListNode and LinkedList classes to see, what it looks like (IIRC these should be correct)...



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


Now, the LinkedList class contains AddItem method, whose body is this:



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


And I don't know why, but when I try to add an item to my linked list, it seems the newNode variable is removed when you get out of scope of the method.


Here is what it looks like when I try to debug the program...


First we start off with en empty linked list Empty Linked List


Then inside the AddItem function I get the following results (it looks like the m_pHead and m_pTail corretly point to the newly created newNode on heap.


Inside Method AddItem()


but when the AddItem() method goes out of scope, this is what I am left with


After AddItem() method


I thought, std::share_ptr is deleted once nothing references the pointer. In my case newNode is referenced by two pointers, m_pHead and m_pTail. Is it really deleted upon leaving the AddItem() method, or is there a flaw in my code I haven't spotted?


Thank you very much for your input, guys.


Aucun commentaire:

Enregistrer un commentaire