实际上不允许容器内的'const'值吗?

时间:2013-05-18 11:09:43

标签: c++ c++11 language-lawyer

为什么我不能将const值的结构放在像std::vector这样的容器中? (我理解编译器报告的技术原因,我只是不确定编译器/集合应该这样做)

例如,非常简单:

struct sample {
    int const a;
};
std::vector<sample> v;
v.push_back( sample{12} );

这给出了关于使用已删除的operator=的错误(至少在GCC中)。但我不明白为什么它应该使用operator=。构造此向量时,不需要使用复制运算符。如果它没有使用复制构造器就地新的,这是完全允许的。例如,以下是可以的:

sample a;
new (&a) sample{12};

调用sample的析构函数也没问题。也就是说,这种类型上有足够的允许操作来构造向量,但我无法这样做。我认为带有rvalue的C ++ 11和移动语义在这里也可能有所帮助,但也许我错了。

标准的哪一部分明确禁止这一点,或者确实是编译错误(不太可能)?

2 个答案:

答案 0 :(得分:6)

我阅读标准(N3290)表示您的push_back有效。

23.2.3第16段(表101-可选序列容器操作)表示push_back只需要T MoveInsertable

23.2.1第13段定义MoveInsertable:以下表达式应有效: allocator_traits<A>::construct(m, p, v);

20.6.8.2第5段指定默认情况下(例如,对于默认分配器)construct调用新位置 - 与您的期望非常相似。

此致 &安培; rzej

答案 1 :(得分:2)

因此,如果您使用的是符合条件的编译器/ stdlib,则会出现:

 vector<T>::push_back(T&&)

临时sample{12}将绑定的重载,导致它使用临时作为参数在v.end()的保留未初始化存储元素上调用T的移动构造函数。不需要复制构造函数或赋值来支持它。

更好的方法是将构造函数添加到sample,然后您可以调用:

 v.emplace_back(12)
除了更简洁之外,

也会避免移动构造函数。

正如其他人所说,您的编译器/ stdlib不符合要求,请升级到更新的版本。