Filling std::vector with objects created elsewhere

How can Foo be destroyed more times than it is created?

The output shows exactly as many creations, as it shows destructions:

            change -> cumulative total    
Foo created!    +1 -> 1
Foo moved       +1 -> 2
Foo destroyed   -1 -> 1
Foo created!    +1 -> 2
Foo moved       +1 -> 3
Foo destroyed   -1 -> 2
reaching end of scope
Foo destroyed   -1 -> 1
Foo destroyed   -1 -> 0 all objects that were created are now destroyed

I thought that Foo would be copied, but the copy constructor is not triggered.

Each time you pass an rvalue to the constructor. That is why the move constructor is used instead of copy constructor.


What is the best way to fill a std::vector with objects created elsewhere without them being destroyed?

Well, by not destroying the objects that you created elsewhere... But usually you should avoid doing that, since it is typically a memory leak.

If you create two objects elsewhere and two objects in a vector, then you end up with having created 4 objects. If you wanted only two objects, then for example create the objects directly into the vector and nowhere else. Like this for example:

fooVector.emplace_back();
fooVector.emplace_back();

When you do

fooVector.push_back(createFoo());

First createFoo() creates a temporary Foo object, this is why you see

Foo created!

Then, that object is "moved" into the vector since it is a prvalue. This is why you see

Foo moved

Now you have an object in the vector, but you also have that temporay object that was created, moving doesn't get rid of that object, it just moves its internals into the object in the vector. You still need to destroy that object once it goes out of scoped and that happens at the end of the full expression giving you the

Foo destroyed

output.


When you make std::move(obj), the state of the moved object is supposed to be a new state which can be destroyed. This happens usually by transferring the data held by the object to a new object (will be constructed using move ctor). and finally the object we have taken its content will be destroyed too.

Now each move operation will construct a new object and leave the old one in a state to be destroyed, hence you have the right output 4 constructions (2 by default ctor and two by move ctor) and the corresponding 4 destructions.