Reputation: 195
I'm trying for the first time to use unique_ptr to grow a binary tree, which basically works like the following:
void growTree(unique_ptr<Node> root){
//do some calculations
root->value = "some value"
for(int i=0;i<2;i++){
unique_ptr<Node> child(new Node);
growTree(move(child));
root->children.push_back(move(child));
}
}
However, I found that the pointer "child" becomes empty before I push them back to root->children
. Why does it lose its values after the recursion? What am I doing wrong here? Thank you!
EDIT1: Now I realized that I can't use the unique_ptr to get the expected value after moving it, so how can I do it (grow a tree) with a smart pointer?
Upvotes: 0
Views: 733
Reputation: 31468
When you move something to someone else you no longer have the moved-from stuff. Why would you expect that?
Once you move the unique_ptr into the growTree call, the original object is now in a valid but empty state (other objects would often be in a valid but unspecified state and certainly not the original state and should not be used again). This is expected and your code is buggy due to trying to use it again.
Upvotes: 1
Reputation: 49028
That's perfectly normal:
Before the push_back
, you are moving child
with std::move
. It literally means that you are giving away child
to growTree
, you don't want it anymore.
After the move, child
is no longer pointing to the original object (because another object has the pointer to it, you moved it after all).
If you want to modify child
, you should pass it as a reference, so that growTree
can modify the the Node
child
points to, without the child
losing the pointer to it:
void growTree(std::unique_ptr<Note>& node);
Upvotes: 2
Reputation: 10011
After you move from an object it is conceptually empty. This is why moving can be more efficient than copying, because you can steal resources which are then gone. Moving from an object twice without giving is a new value is a bug. Additionally a unique_ptr
has unique ownership of an object, consequently there can only be one, so you cannot pass it to both growTree
and root->children
.
To solve the issue you must decide who owns the child
. std::move
the child there and keep a stable reference to that place in the other place. If the place is runtime dependent you can use a shared_ptr
instead.
Upvotes: 2