为什么在 std::vector::push_back(T object) 方法中构造对象时调用析构函数?

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

我这里有这一行:

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

我希望 SomeClass 会被构建并移动到向量的后面,没有任何副本。但是,析构函数在这里被调用。我尝试用 std::move:

修改它
someSTLVector.push_back(std::move(SomeClass(...)));

但结果没有改变。

我还尝试在 SomeClass 中定义以下内容:

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

这也无济于事,析构函数仍然被调用。请注意,SomeClass 包含作为成员的引用

很明显 SomeClass 被构建,然后被复制到向量中。我不想避免这种情况,而是将其构建为矢量的一部分(或至少移动到矢量,避免任何复制)。 SomeClass 管理在析构函数中释放的资源。如果复制对象时调用了析构函数,则资源被释放,对象变为无效,指向不再存在的资源。

如何实例化一个 class,其中生成的对象将放置在向量的后面,但不会在此过程中复制(因此不会被销毁)?

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.

确实如此。那将是您传递给移动构造函数的临时对象:

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

存在用于初始化临时对象的语法。

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).

您已经设法避免了复制。为避免移动,您可以使用 emplace_back 成员函数而不是 push_back:

someSTLVector.emplace_back(...);

这会将参数直接转发给元素的构造函数。


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.

如果您的析构函数释放了一些资源,那么默认的移动构造函数/赋值可能没有执行您希望它们执行的操作。参见五/三规则。

移动的对象仍然被破坏。所以你的 SomeClass 可能被移动到向量中(你可以在你的移动构造函数中添加一个 std::cout << 消息来验证)但它随后也被破坏了。

您可以调用 std::vector::emplace_back 将项目构建到向量中。但是,这仍然不能保证您的对象不会被移动(例如,如果向量需要增长,它可以分配更多 space 然后将所有对象移动到新存储,然后在其原始位置销毁它们).

如果您有一些资源要在析构函数中释放,您需要确保在对象被移动时不会执行该释放。通常将构造函数 "empty" 移出移出的对象(例如,在该方法中给定 SomeClass(SomeClass&& other),您会将 other 修改为 "empty it")。然后你的析构函数可以查看它是否是 "empty"(已被移出)并且不会释放你持有的任何资源。