为什么std :: vector :: reserve会调用复制构造函数?

ifs*_*ife 7 c++ gcc stl vector

为什么以下代码不适用于g++版本4.9.2?如果我尝试构建它,编译器会抱怨在向量被告知要保留更多内存的行中缺少复制构造函数.

#include <vector>

class Number
{
public:
    explicit Number(const int& i) : _value(i) {}

    Number(const Number& other) = delete;
    Number& operator=(const Number& other) = delete;

private:
    int _value;
};


int main(int argc, char** argv)
{
    std::vector<Number> numbers;
    numbers.reserve(8);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么编译器甚至会在向量的存储大小增加时尝试调用已删除的复制构造函数?无论如何,矢量中没有对象.

Yak*_*ont 12

简短的回答是因为语言标准这样说.但这并不有趣.

如果容器中有数据,则Reserve可以调用复制构造函数.

reserve它的哪个分支(没有副本或副本)在运行时确定,而不是编译时.

您看到编译时错误,而不是运行时错误.您已声明不应编译可能导致您的对象复制的代码.

编译器不分析其中的reserve位置,向自身证明向量为空,使用它来确定reserve将运行哪个代码分支,然后说"没问题".相反,它编译包含副本的函数,并生成错误.

理论上,只允许预分配(空的)和安置构造(直到预定限制)的容器不需要具有任何类型的复制或移动构造的对象.在std编写容器库时,emplace构造是不切实际的,因此std容器库中不存在此选项:在C++ 11之前,将对象放入a的唯一方法vector是复制它.

std::dynarray 接近,但它不会让你的缓冲区一半未使用并逐渐填充.