Reputation: 735
I am working on a tree structure that has a vector of unique pointers
as a class member. While working on it, I realised that I am not sure how to initialize a unique pointer as a class member if the object, which the unique pointer will own, comes as a parameter.
So, I am simply asking: How I should initialize unique pointers as a class member if the object that will be owned comes as a parameter?
Should I use new ( addTheObject(new Object())
) and then use std::make_unique
? Should I pass the object as unique_ptr ( addTheObject(std::unique_ptr<Object>& theObject)
) and use std::move(theObject)
?
What is the correct way to handle this?
In case you need more concrete example:
I have a DT_Node
class, which is a node of a tree, and I will construct a tree using DT_Node
.
DT_Node
has a method called addChild()
that is used to insert children into its node vector.
DT_Node
will be used in different cpp files to construct a tree, which means another cpp file will use addChild()
method to add the children of the node.
// DT_Node.hpp
class DT_Node
{
public:
DT_Node();
virtual ~DT_Node();
virtual void decide() = 0;
virtual void addChild( ??? );
private:
std::vector< std::unique_ptr<DT_Node> > mNodes;
};
// DT_Node.cpp
DT_Node::DT_Node()
{
}
DT_Node::~DT_Node()
{
mNodes.clear();
}
void DT_Node::addChild( ??? )
{
???
}
Upvotes: 2
Views: 2725
Reputation: 9705
std::unique_ptr
keeps the own of the pointed object. That means if you want to pass it as a parameter, you have to move the ownership.
Something like (note the move
and &&
-reference):
void addChild(std::unique_ptr<Node>&& iNode) {
mNodes.emplace_back(std::move(iNode));
}
Finally, I'd strongly suggest you take a look at this Herb Sutter Video. It gives some useful advice on data structures with smart pointers.
Upvotes: 3
Reputation: 5156
Assuming that DT_Node is not a pure virtual base class , this is the code snippet. You will need a copy constructor as well. Two versions of the addChild is used which is self explanatory.
class DT_Node
{
public:
DT_Node();
DT_Node(const DT_Node& other); // copy constructor will be needed
virtual void addChild(std::unique_ptr<DT_Node>&& node); // move from source
virtual void addChild(const std::unique_ptr<DT_Node>& node); //non destructible source
private:
std::vector<std::unique_ptr<DT_Node> > mNodes;
};
void DT_Node::addChild(std::unique_ptr<DT_Node>&& node)
{
mNodes.push_back(std::move(node));
}
void DT_Node::addChild(const std::unique_ptr<DT_Node>& node)
{
std::unique_ptr<DT_Node> new_node = std::make_unique<DT_Node>(*node);
mNodes.push_back(std::move(new_node));
}
Upvotes: 0
Reputation: 28987
What you need is:
void DT::Node::addChild(std::unique_ptr<DT_Node>&& child) {
mNodes.emplace_back(std::move(child));
}
By the way, your title is misleading. The unique_ptr is not a member (it is contained in a member), and you are not definitely not initializing a member (for which you would use the member initializer list syntax in the constructor).
Upvotes: 8