为什么我不能将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和移动语义在这里也可能有所帮助,但也许我错了。
标准的哪一部分明确禁止这一点,或者确实是编译错误(不太可能)?
答案 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不符合要求,请升级到更新的版本。