我将对象存储在std::vector
中,我希望尽可能避免调用析构函数。
我用移动的方法替换了复制构造函数和赋值:
class Object
{
Object(const Object&) = delete;
Object(Object&&);
Object& operator=(const Object&) = delete;
Object& operator=(Object&&);
[...]
};
我正在初始化它:
std::vector<Object> container;
container.reserve(42) // Reserve a lot in order to be sure it won't be a problem
然后,我用emplace_back添加两个元素(构造函数接受一个int
参数):
container.emplace_back(1);
container.emplace_back(3);
直到那里,一切都很好。但后来我想在最后一个元素emplace之前插入一个元素:
auto it = container.end();
it--; // Last position.
it--; // Before last position.
container.emplace(it, 2);
但这里有一个析构函数。
我试图找到Valgrind的原因,它显示emplace
函数调用_M_insert_aux
来调用我的析构函数。
我怎么能避免这种情况?
答案 0 :(得分:2)
你无法避免这种情况。这就是vector
的工作原理。它是一个连续的数组。将新元素插入连续数组的唯一方法是向下移动旧元素。这意味着使用移动分配将它们移动到新的位置。
因此,如果您有以下向量及其内容:
[5][12][16]
如果你在第二个元素之后插入,那么在某些时候你有这个:
[5][12][*][16]
哪里&#34; *&#34;是移动元素的值。
然后是emplace
。 emplace
明确地将构建值;这是它的用途。但是,第3个元素中已经存在一个活动对象:移动的值。
因此,在可以在其位置构造新对象之前,必须销毁。因此必须调用析构函数。
如果您使用insert
而不是emplace
,那么您仍然会调用析构函数。但那将是您传递给insert
函数的对象的析构函数。
所以有一个&#34;额外&#34;析构函数叫某处。
但实际上,你不应该担心析构函数的数量。专注于绝对成本。一般来说,如果你有一个只移动类型,那么移动值的析构函数会很便宜。