简体   繁体   English

为什么std :: vector :: emplace在没有调用任何拷贝构造函数的情况下调用析构函数?

[英]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.

相关问题 为什么在调用std :: vector :: emplace_back()时调用复制构造函数? - Why is copy constructor called in call to std::vector::emplace_back()? 为什么std :: map emplace需要在gcc上使用复制构造函数? - Why does std::map emplace need a copy constructor on gcc? 为什么std :: vector :: reserve会调用复制构造函数? - Why does std::vector::reserve call the copy constructor? 为什么vector.emplace_back调用move-constructor? - why does vector.emplace_back call the move-constructor? 为什么 std::vector 在离开不同的 scope 时调用析构函数? - Why does std::vector call the destructor while leaving a different scope? 为什么在std :: vector的初始化列表中调用复制构造函数? - Why copy constructor is called in std::vector's initializer list? 为什么矢量 <T> :: \\ templace_back,这样T有一个删除的拷贝构造函数,无法编译? - Why does vector<T>::emplace_back, such that T has a deleted copy constructor, fail to compile? 为什么vector :: push_back和emplace_back调用value_type :: constructor两次? - Why does vector::push_back and emplace_back call value_type::constructor twice? 返回std :: vector时未调用复制构造函数 - copy constructor not called when returning a std::vector 为什么 std::vector 构造函数通过复制接受初始化列表? - Why does the std::vector constructor accept initializer list by copy?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM