Reputation: 5917
I am storing objects inside a std::vector
, and I want to avoid calling destructor as much as possible.
I replaced copy constructor and assignments by move ones:
class Object
{
Object(const Object&) = delete;
Object(Object&&);
Object& operator=(const Object&) = delete;
Object& operator=(Object&&);
[...]
};
I am initializing it like this:
std::vector<Object> container;
container.reserve(42) // Reserve a lot in order to be sure it won't be a problem
Then, I add two elements with emplace_back (the constructor takes one int
parameter):
container.emplace_back(1);
container.emplace_back(3);
Until there, everything is fine. But then I want to insert an element before the last one with emplace:
auto it = container.end();
it--; // Last position.
it--; // Before last position.
container.emplace(it, 2);
But here a destructor is called.
I tried to locate why with Valgrind, it appears emplace
function calls _M_insert_aux
that call my destructor.
How could I avoid that?
Upvotes: 3
Views: 2121
Reputation: 474036
You can't avoid that. This is simply how a vector
works. It's a contiguous array. The only way you can insert a new element into a contiguous array is to move the old elements down. That means using move assignment to move them into their new positions.
So if you have the following vector, and their contents:
[5][12][16]
If you insert after the second element, then at some point you have this:
[5][12][*][16]
Where "*" is the value of a moved-from element.
Then comes the emplace
. emplace
explicitly will construct the value in place; that's what its for. However, there is already a live object in the 3rd element: the moved-from value.
Therefore, this object must be destroyed before the new object can be constructed in its place. Hence the destructor must be called.
If you used insert
rather than emplace
, then you would still have a destructor be called. But that would be the destructor of the object you pass to the insert
function.
So there's going to be an "extra" destructor called somewhere.
But really, you shouldn't be worried about the number of destructor calls. Focus on absolute costs. Generally speaking, if you have a move-only type, the destructor for a moved-from value will be cheap.
Upvotes: 2