我写了一个小的“懒矢量”类(或延迟矢量),它应该看起来像std::vector
,可以在std::vector
被使用的任何地方使用,但是它“懒洋洋地”加载它的元素,即每当有人访问元素n
时,它将从磁盘加载元素n
(可能还有一些)。 (原因是在我的应用程序中,并非所有元素都适合内存。)
以下是此LazyVector
类,但使用此类向量的const
成员函数存在问题,请参阅下文。
template<class T>
class LazyVector {
std::vector<T> elems_;
void fetchElem(unsigned n){
// load the n-th elem from disk into elems_ etc
}
public:
const T& operator[](unsigned n) const {
fetchElem(n); // ERROR: ... discards qualifiers
return elems_[n];
}
T& operator[](unsigned n) {
fetchElem(n);
return elems_[n];
}
// and provide some other std::vector functions
};
正如我所说,当const
成员函数要求LazyVector
的元素时,会出现问题。根据{{1}}的性质,访问元素不 LazyVector
,即它将更改下面的向量const
,这在此上下文中是被禁止的。 vec
成员函数必须为foo
且无法更改。我该如何解决这个问题?
const
答案 0 :(得分:7)
您可以在LazyVector类的实现中使用可变成员数据或const_cast。因此,您可以创建消耗类所需的constness幻觉,而不是实际上是const。
答案 1 :(得分:4)
在elems_数据成员上使用mutable关键字。
答案 2 :(得分:3)
const运算符用于表示对象在逻辑上是常量 您的数据在磁盘上的事实既不在这里,也不在您的对象没有改变状态,因此您可以将实际保存数据的工作委托给另一个对象缓存(存储数据的地方是实现细节而不是对象状态)。
class LazyVector
{
public:
int const& operator[](int index) const
{
data->fetchElement(index);
return data->get(index);
}
private:
std::auto_ptr<LazyDataCache> data;
};
这里的数据是指针(智能指针但仍然是指针)。只要指针没有改变,你就不会改变LazyVector的成本。但是你仍然可以在数据所指向的对象上调用非const方法(记住它是const指针所指向的指针)。
答案 3 :(得分:2)
对于此类内容,mutable
关键字适用于。将缓存作为可变对象放入您的类中。这是因为您的缓存似乎没有改变对象的逻辑内容/状态(即向量的元素或其大小不会改变)。
const
方法并未声明它们不会物理更改您的对象。他们声明他们不会改变对象的抽象值。抽象的实现细节仍可能由const函数更改。
可变性是针对这种情况的。使您的向量可变或添加包含某种缓存条目的可变缓存成员。
阅读Anthony Williams的What are the semantics of a const member function答案。
答案 4 :(得分:1)
将elems_
声明为mutable
:
mutable std::vector<T> elems_;
你还可以做其他事情,但这是支持的方式。
编辑:另一种方法是添加另一个成员并在构造函数中设置它:
std::vector<T> *mutable_elems_;
mutable_elems_(&elems_)
答案 5 :(得分:1)
这样做的粗略方法是
LazyVector* p = const_cast<LazyVector*>(this);
p->fetch();
我想有更好的方法可以做到这一点。但这会奏效。