为什么要将类型T放置在需要移动可构造的向量的末尾

Why should a type T to be emplaced at the end of a vector required to be move constructible?

本文关键字:向量 移动 类型 为什么      更新时间:2023-10-16

为什么公共构造函数(和析构函数)不足以将类型为T的对象放置在向量的后面?以下代码段格式不正确。

#include <vector>
struct Foo {
Foo() {}
Foo(int) {}
~Foo() {}
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
};
int main() {
std::vector<Foo> vfoo(10);
vfoo.emplace_back();
}

emplace_back要求Foo至少是可移动构造的,但由于移动构造函数和复制构造函数一起被删除,因此此代码无法编译。但我设想emplace_back使用placementnew调用默认构造函数。

在您的示例中,向量是用10元素构造的。

然后你加一个。如果capacity()中没有更多的空间,则必须分配一个新的缓冲区,必须将已经存在的10个元素移到其中,然后添加您的新元素。

您会注意到上面的单词move,这就是您需要move ctor的原因。

更重要的是,即使你没有元素,或者你小心地确保有足够的容量,编译器也不会知道:移动现有元素的代码将被编译(如果不运行),你会得到错误。

vector中缺少"推回,我保证已经有容量"方法。再加上"设置容量,丢弃任何现有元素",您就可以添加元素,而不需要移动ctor(或复制ctor回退)。在emplace发明之前,所有的add元素都需要一个拷贝或移动:在C++11之前,所有add元素都要求一个拷贝。缺少这两个具有奇怪语义的方法,仅仅是为了允许不可移动的类型有限地使用vector,这并不奇怪。

我鼓励您编写一个具有这两个扩展(或类似扩展)的容器,并建议将其添加到C++中:这可能也有助于高性能用例(编译器擅长证明我确实根据自己的经验确保了足够的容量)。