mmirror
mmirror

Reputation: 195

unique_ptr becomes empty after moving

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

Answers (3)

Jesper Juhl
Jesper Juhl

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

Rakete1111
Rakete1111

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

nwp
nwp

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

Related Questions