4

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

例如,一些非常简单的事情:

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

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

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

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

标准的哪一部分特别不允许这样做,或者确实是编译器错误(不太可能)?

4

2 回答 2

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调用placement new - 很像您的期望。

问候, &rzej

于 2013-05-18T12:04:38.003 回答
2

因此,如果您使用的是一致的编译器/stdlib,将会有:

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

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

更好的方法是添加一个构造函数sample,然后你可以调用:

 v.emplace_back(12)

除了更简洁之外,它还将避免移动构造函数。

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

于 2013-05-18T14:37:16.480 回答