设计一个懒惰的载体:用const的问题
-
23-08-2019 - |
题
我写了一个小的“懒载体”类(或,延迟矢量),其应该看起来像任何地方使用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
的元件。由LazyVector
的性质,访问一个元素是不 const
,即,它会改变下面的矢量vec
,这在该上下文中禁止的。该foo
成员函数必须const
并且不能更改。我该如何解决这个问题?
class Foo {
LazyVector<const std::string*> vec;
void fct(int n) const { // fct must be const
const std::string* str = vec[n];
// do something with str
}
};
解决方案
您可以使用可变数据成员或const_cast会在你LazyVector类的实现。因此,你可以创建你的消费类所需要的常量性的假象,而无需实际是常量。
其他提示
在使用可变关键字所述elems_数据成员。
在常量操作者用于显示该对象在逻辑上是常量。结果 您的数据在磁盘上的事实是不伦不类的对象不改变状态,因此您可以委托工作,为数据实际持有到另一个对象缓存(其中存储的数据是一个实现细节,而不是部分对象状态)。
class LazyVector
{
public:
int const& operator[](int index) const
{
data->fetchElement(index);
return data->get(index);
}
private:
std::auto_ptr<LazyDataCache> data;
};
下面数据是一个指针(智能指针但仍然是一个指针)。只要指针不会改变你不改变LazyVector成本的烦躁。但仍可以调用非const的方法上的对象指向由数据(记住它是该指针是常量不是对象指向)。
有关这样的事情,在mutable
关键字是。把你的缓存为可变对象到类。那是因为你的缓存似乎无法改变你的对象的逻辑内容/状态(你的载体的即元素或它的大小不会改变)。
const
方法并不说明他们没有实际改变你的对象。他们指出,他们不会改变你的对象的抽象价值。被抽象化了的实施细则仍可能通过const函数来改变。
在可变为这种例。让你的矢量可变或添加包含某种缓存条目的可变缓存成员。
读取什么的语义一个const成员函数通过安东尼威廉姆斯回答。
声明elems_
作为mutable
:
mutable std::vector<T> elems_;
还有其他的东西可以做,但是这是做它的支持方式。
编辑:这样做的另一种方法是添加另一部件,并将其设置在构造:
std::vector<T> *mutable_elems_;
mutable_elems_(&elems_)
这样做的一个粗的方法是
LazyVector* p = const_cast<LazyVector*>(this);
p->fetch();
我想会有这样做的更好的方法。但是,这会工作。