I have only been using raw pointers for linked list with templates. For example, the member data, Node and when I am inserting a node one of the
There are basically two alternatives to set up a smart-pointer enhanced list:
Using std::unique_ptr:
template
struct Node
{
Node* _prev;
std::unique_ptr _next;
T data;
};
std::unique_ptr > root; //inside list
That would be my first choice. The unique-pointer _next takes care there are no memory leaks, whereas _prev is an observing pointer. Copy and such things, however, need to be defined and implemented by hand.
Using shared_ptr:
template
struct Node
{
std::weak_ptr _prev; //or as well Node*
std::shared_ptr _next;
T data;
};
std::shared_ptr > root; //inside list
This is the safer alternative, but less performant than with a unique-pointer. Moreover, it is copyable by design.
In both the idea is that one node owns the complete remaining list. Now when a node goes out of scope, there is no danger that the remaining list becomes a memory leak, as the nodes are iteratively destructed (starting from the last one).
The _prev pointer is in both options only an observing pointer: it's task is not to keep the previous nodes alive, but only to provide a link to visit them.
For that, a Node * is usually sufficient (--note: observing pointer means you never do memory related stuff like new, delete on the pointer).
If you want more safety, you can also use a std::weak_ptr for that. this prevents from things like
std::shared_ptr > n;
{
list li;
//fill the list
n = li.root->next->next; //let's say that works for this example
}
n->_prev; //dangling pointer, the previous list does not exists anymore
Using a weak_ptr, you can lock() it and in this way chack whether _prev is still valid.