我在这里有这行:
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
管理在析构函数中释放的资源。如果在复制对象时调用了析构函数,则资源将被释放并且对象变为无效,指向不再存在的资源。
我如何实例化一个类,在该类中将生成的对象放置在向量的后面,但在过程中不会被复制(并因此被销毁)?
我希望可以构造SomeClass并将其移到向量的背面,而没有任何副本。
那会发生。
但是,析构函数在这里被调用。
的确。那将是您传递给move构造函数的临时对象:
someSTLVector.push_back(SomeClass(...)); ^^^^^^^^^^^^^^
存在用于初始化临时对象的语法。
很明显,先构造SomeClass,然后将其复制到向量中。
好吧,已移动准确地说。尽管移动是一种复制形式。
我不想避免这种情况,而是将其构造为向量的一部分(或至少移至向量,以避免任何复制)。
您已经设法避免了复制。为了避免移动,可以使用emplace_back
成员函数代替push_back
:
someSTLVector.emplace_back(...);
这会将参数直接转发到元素的构造函数。
如果在复制对象时调用了析构函数,则资源将被释放并且对象变为无效,指向不再存在的资源。
如果析构函数释放了一些资源,则默认的move构造函数/赋值可能没有按照您希望它们执行的操作进行。参见五/三规则。
被移动的对象仍然被破坏。因此,您的SomeClass
可能已移到向量中(可以在move构造函数中添加std::cout <<
消息进行验证),但随后也会被销毁。
您可以调用std::vector::emplace_back
将项目直接构建到向量中。但是,这仍然不能保证您的对象不会移动(例如,如果矢量需要增长,它可以分配更多空间,然后将所有对象移动到新存储中,然后在其原始位置销毁它们)。
如果您有一些资源要在析构函数中释放,则需要确保在移动对象时不要释放该资源。通常,将构造函数“移出”从移出的对象移出(例如,在该方法中给定的SomeClass(SomeClass&& other)
中,您将other
修改为“移出”)。然后,您的析构函数可以查看它是否为“空”(已从中移出),而不会释放您持有的任何资源。