如果使用诸如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
,因此这里没有未定义行为)?
编辑 仅为了防止进一步混淆:我确实想要修改元素,即容器的内容但不包括容器本身(大小和/或内存位置)。
std::vector
的数据可以通过调用operator[]
进行更改。由于您已经编写了A::X
,因此a.x(1)++;
是完全合法的,并且会修改向量的内容。 - David Schwartzstd::vector
,它只有3个指针作为数据(数据的开始和结束以及缓冲区的结束)。这些保持不变。 - Walter