【发布时间】:2013-02-11 16:07:09
【问题描述】:
对于容器类,例如std::vector,有两个不同的常量概念:容器的概念(即它的大小)和元素的概念。似乎std::vector 混淆了这两者,以至于下面的简单代码无法编译:
struct A {
A(size_t n) : X(n) {}
int&x(int i) const { return X[i]; } // error: X[i] is non-const.
private:
std::vector<int> X;
};
请注意,即使std::vector 的数据成员(指向数据的开始和结束以及分配缓冲区结束的三个指针)没有被调用它的operator[],这个成员不是const——这不是一个奇怪的设计吗?
还要注意,对于原始指针,这两个常量性概念被巧妙地分开,因此相应的原始指针代码
struct B {
B(size_t n) : X(new int[n]) {}
~B() { delete[] X; }
void resize(size_t n); // non-const
int&x(int i) const { return X[i]; } // fine
private:
int*X;
};
工作得很好。
那么当使用std::vector(不使用mutable)时,正确/推荐的处理方法是什么?
是const_cast<>,如
int&A::x(int i) const { return const_cast<std::vector<int>&>(X)[i]; }
认为可以接受(X 已知不是const,所以这里没有 UB)?
EDIT 只是为了防止进一步混淆:我确实想修改元素,即 容器的内容,而不是容器本身(大小和/或内存位置)。
【问题讨论】:
-
std::vector的数据可以通过调用operator[]来更改。正如您所写的A::X,a.x(1)++;是完全合法的,并且会修改向量的内容。 -
@DavidSchwartz 向量的 contents 不是它的实际 data(尽管您可以在逻辑上将它们关联起来)。如果您检查
std::vector,它只有 3 个指针作为数据(数据的开头和结尾以及缓冲区的结尾)。这些保持不变。
标签: c++ constants containers