Karlovsky120
Karlovsky120

Reputation: 6352

Why is the destructor called upon construction of an object in std::vector::push_back(T object) method?

I have this line here:

someSTLVector.push_back(SomeClass(...));

I was hoping what SomeClass would be constructed and moved to the back of the vector, without any copies. However, the destructor got called here. I tried amending this with an std::move:

someSTLVector.push_back(std::move(SomeClass(...)));

but the result didn't change.

I also tried defining the following in the SomeClass:

SomeClass(SomeClass&&) = default;
SomeClass& operator= (SomeClass&&) = default;
SomeClass(const SomeClass&) = delete;
SomeClass& operator= (const SomeClass&) = delete;

That didn't help either, the destructor was still called. Note that the SomeClass contains a reference as a member

It's apparent that SomeClass gets constructed and then copied into the vector. I want't to avoid that and have it be constructed as a part of the vector (or at least moved to the vector, avoiding any copying). SomeClass manages a resources which gets released in the destructor. If the destructor is called when copying the object, the resource is released and the object becomes invalid, pointing to a resource that no longer exists.

How can I instantiate a class where the resulting object will be placed to the back of the vector, but not copied (and thus destroyed) in the process?

Upvotes: 1

Views: 81

Answers (2)

eerorika
eerorika

Reputation: 238401

I was hoping what SomeClass would be constructed and moved to the back of the vector, without any copies.

That is what does happen.

However, the destructor got called here.

Indeed. That would be the temporary object that you passed to the move constructor:

someSTLVector.push_back(SomeClass(...));
                        ^^^^^^^^^^^^^^

That there is syntax for initialisation of a temporary object.

It's apparent that SomeClass gets constructed and then copied into the vector.

Well, moved to be exact. Although moving is a form of copying.

I want't to avoid that and have it be constructed as a part of the vector (or at least moved to the vector, avoiding any copying).

You've already managed to avoid the copying. To avoid the move, you can use the emplace_back member function instead of push_back:

someSTLVector.emplace_back(...);

This forwards the arguments directly to the constructor of the element.


If the destructor is called when copying the object, the resource is released and the object becomes invalid, pointing to a resource that no longer exists.

If your destructor releases some resources, then the defaulted move constructor / assignment are probably not doing what you would want them to do. See rule of five / three.

Upvotes: 4

Oliver Dain
Oliver Dain

Reputation: 9953

An object that is moved is still destructed. So your SomeClass is probably moved into the vector (you could add a std::cout << message in your move constructor to verify) but it is then also destructed.

You can call std::vector::emplace_back to have the item constructed right into the vector. However, that still doesn't guarantee your object won't be moved (e.g. if the vector needs to grow it can allocate more space and then move all the objects to the new storage and then destroy them in their original location).

If you have some resource you're releasing in the destructor you need to ensure you don't do that release if the object was moved. Typically move constructors "empty" out the moved-from object (e.g. given SomeClass(SomeClass&& other) in that method you'd modify other to "empty it"). Then your destructor can see if it's "empty" (has been moved from) and not release whatever resources you're holding.

Upvotes: 2

Related Questions