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

时间:2014-12-14 15:30:44

标签: c++ gcc vector stl

为什么以下代码不适用于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;
}

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

1 个答案:

答案 0 :(得分:11)

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

如果容器中有数据,保留可以调用复制构造函数。

它遵循reserve的哪个分支(没有复制或复制)是在运行时确定的,而不是编译时。

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

编译器不会分析reserve所在的位置,向自身证明向量是空的,用它来确定代码reserve的哪个分支将运行,然后说&#34;没问题& #34 ;.相反,它编译包含副本的函数,并生成错误。

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

std::dynarray接近,但它不会让缓冲区被半未使用并逐渐填充。