设计一个懒惰的向量:const的问题

时间:2009-02-15 06:34:10

标签: c++ vector const lazy-loading

我写了一个小的“懒矢量”类(或延迟矢量),它应该看起来像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

6 个答案:

答案 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();

我想有更好的方法可以做到这一点。但这会奏效。