【发布时间】:2011-02-15 02:31:33
【问题描述】:
this answer 上的 cmets 让我开始思考 constness 和排序的问题。我玩了一下,将我的问题减少到以下代码:
#include <vector>
int main() {
std::vector <const int> v;
}
不会编译 - 你不能创建一个 const int 的向量。显然,我应该知道这一点(并且在智力上我做到了),但我以前从来不需要创造这样的东西。但是,它对我来说似乎是一个有用的构造,我想知道是否有任何方法可以解决这个问题 - 我想将东西添加到向量(或其他),但一旦添加就不应更改它们。强>
可能有一些令人尴尬的简单解决方案,但这是我以前从未考虑过的。 我可能不应该提到排序(我可能会问另一个问题,请参阅this 了解提问的困难)。我真正的基本用例是这样的:
vector <const int> v; // ok (i.e. I want it to be OK)
v.push_back( 42 ); // ok
int n = v[0]; // ok
v[0] = 1; // not allowed
【问题讨论】:
-
对于那些想知道为什么上述不能保证工作的人是容器中的元素必须是可复制构造和可复制分配的。后者不适用于 const 对象。 (请注意,上面的内容在 VS 中可以使用,因为在这种情况下它不使用可复制分配的要求,但是 GCC 会这样做并且它会失败。不过,两种实现都是正确的。)
-
我不确定我是否真的理解这个问题。向量中使用的类型必须是Assignable,因此即使您使用代理对象尝试在某个级别为包装对象添加常量,
op[]、at或derefenced 的迭代器可以从另一个外部创建的代理对象分配,因此代理的实现必须很容易被破坏。我错过了什么吗? -
@GMan VS 真的允许这样做吗?如果确实如此,我会认为它会坏掉。你说两者都是正确的依据是什么?
-
@Donal Fellows:即使在 C++03 中,您也可以使用
const类型执行就地销毁然后放置复制构造,因此构建const类型的容器在技术上是可行的。 -
@Neil:确实,VS(真的是 Dinkumware)在添加元素和复制元素时会使用复制构造函数。相反,GCC 使用赋值来分配值。我说两者都是正确的原因是实现可以做任何他们想做的事情。然而,有人可能会争辩说 VS 允许这是一种“扩展”,因为 const 类型不满足容器要求,而且它恰好工作的事实仅仅是一个实现细节。