I'm trying to implement the linked list by indirect pointer, which introduced on the TED Talk.
I refer to felipec's implementation on github and made an version by raw pointer, this is the github link.
This is part of the full code, _find is a function that can find the indirect pointer of target node, which means *indirect == target node :
//...
struct Node {
int data;
Node *next;
Node()
: data(0), next(nullptr) {}
Node(int _d, Node *_next = nullptr)
: data(_d), next(_next) {}
~Node() { puts("~Node"); }
};
//...
List::Node **List::_find(const int target)
{
Node **indirect = &head;
while (*indirect && (*indirect)->data != target)
indirect = &(*indirect)->next;
return indirect;
}
I wanna make a smart pointer version of this. I use std::unique_ptr for the next pointer in Node, and std::shared_ptr for the head pointer in List.
But in the part Node **indirect = &head, I have no idea for how to design it by smart pointer, I have wrote this:
//...
struct Node {
int data;
std::unique_ptr<Node> next;
Node()
: data(0), next(nullptr) {}
Node(int _d, std::unique_ptr<Node> &_next)
: data(_d), next(std::move(_next)) {}
~Node() { puts("~Node"); }
};
//...
List::Node **List::_find(const int target)
{
Node **indirect = &(head.get());
while (*indirect && (*indirect)->data != target)
indirect = &(*indirect)->next;
return indirect;
}
Apparently, Node **indirect = &(head.get()) is not an good idea since the get function return a rvalue that it point to. But what I need is the pointer object that point to the target, the code even can't be compiled.
Thus, there is two question
How could I get the address of the target object in smart pointer?
Did I use the smart pointer in correct way? Should I change
shared_ptrtounique_ptr, or just not use smart pointer for it?
Any additional supplements and recommendations are appreciated.
CodePudding user response:
How could I get the address of the target object in smart pointer?
I think you mean "the address of the pointer in the smart pointer", because the address of the target object is just what you get with .get(). std::unique_ptr does not offer any interface to access it's pointer member directly, so it is impossible.
Did I use the smart pointer in correct way? Should I change shared_ptr to unique_ptr, or just not use smart pointer for it?
Using std::unique_ptr is the correct thing to do. You don't need shared_ptr because there are never two owners of any given node.
In your first code indirect is a pointer to a raw pointer in the Node/List structure. Since you changed these to smart pointers, indirect should also become a pointer to a smart pointer:
std::unique_ptr<List::Node> *List::_find(const int target)
{
std::unique_ptr<Node> *indirect = &head;
while (*indirect && (*indirect)->data != target)
indirect = &(*indirect)->next;
return indirect;
}
Although it would be more idiomatic to return a reference instead:
std::unique_ptr<List::Node> &List::_find(const int target)
{
std::unique_ptr<Node> *indirect = &head;
while (*indirect && (*indirect)->data != target)
indirect = &(*indirect)->next;
return *indirect;
}
(I am assuming that this is a private helper function and not actually the interface of the List class, in which case there would be problems with either implementation.)
