为什么在 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"(已被移出)并且不会释放你持有的任何资源。
我这里有这一行:
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"(已被移出)并且不会释放你持有的任何资源。