[英]Why does std::vector::emplace call destructor without any copy constructor called?
I am storing objects inside a std::vector
, and I want to avoid calling destructor as much as possible. 我在
std::vector
存储对象,我想避免尽可能多地调用析构函数。
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): 然后,我使用emplace_back添加两个元素(构造函数接受一个
int
参数):
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. 我试着用Valgrind的定位原因,它似乎
emplace
函数调用_M_insert_aux
调用析构函数。
How could I avoid that? 我怎么能避免这种情况?
You can't avoid that. 你无法避免这种情况。 This is simply how a
vector
works. 这就是
vector
工作原理。 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
。 emplace
explicitly will construct the value in place; emplace
明确将建设到位的价值; that's what its for. 这就是它的用途。 However, there is already a live object in the 3rd element: the moved-from value.
但是,第3个元素中已经存在一个活动对象:移动的值。
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. 如果你使用
insert
而不是emplace
,那么你仍然会调用析构函数。 But that would be the destructor of the object you pass to the insert
function. 但那将是您传递给
insert
函数的对象的析构函数。
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.
一般来说,如果你有一个只移动类型,移动值的析构函数将是便宜的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.