0

我写了一个小“惰性向量”类(或延迟向量),它应该看起来像 astd::vector并且可以在使用 astd::vector的任何地方使用,但它会“惰性”加载它的元素,即它会加载元素n(可能还有更多)每当有人访问 element 时从磁盘中获取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 
  }
};
4

6 回答 6

7

您可以在 LazyVector 类的实现中使用可变成员数据或 const_cast。因此,您可以创建消费类所需的 const 错觉,而无需实际成为 const。

于 2009-02-15T06:40:20.910 回答
4

在 elems_ 数据成员上使用mutable关键字。

于 2009-02-15T06:37:55.083 回答
3

const 运算符用于表明对象在逻辑上是 const。
您的数据在磁盘上的事实既不是在这里也不是您的对象没有改变状态,因此您可以将实际保存数据的工作委托给另一个对象缓存(存储数据的位置是实现细节,而不是对象状态)。

class LazyVector
{
    public:
        int const& operator[](int index) const
        { 
            data->fetchElement(index);
            return data->get(index);
        }
    private:
        std::auto_ptr<LazyDataCache>   data;
};

这里的 data 是一个指针(一个智能指针,但仍然是一个指针)。只要指针不改变,你就不会改变 LazyVector 的成本。但是您仍然可以在 data 指向的对象上调用非 const 方法(请记住,指针是 const 而不是指向的对象)。

于 2009-02-15T08:32:19.023 回答
2

对于这样的事情,mutable关键字是for。将缓存作为可变对象放入您的类中。那是因为您的缓存似乎不会改变对象的逻辑内容/状态(即向量的元素或它的大小不会改变)。

const方法并未声明它们不会物理更改您的对象。他们声明他们不会改变对象的抽象值。抽象出来的实现细节仍然可以被 const 函数改变。

可变的适用于这种情况。使您的向量可变或添加包含某种缓存条目的可变缓存成员。

阅读 Anthony Williams 的What are the semantics of a const member function answer。

于 2009-02-15T06:39:57.043 回答
1

声明elems_mutable

mutable std::vector<T> elems_;

您还可以做其他事情,但这是受支持的方式。

编辑:另一种方法是添加另一个成员并将其设置在构造函数中:

std::vector<T> *mutable_elems_;

mutable_elems_(&elems_)

于 2009-02-15T06:39:08.277 回答
1

这样做的一种粗略方法是

LazyVector* p = const_cast<LazyVector*>(this);
p->fetch();

我想会有更好的方法来做到这一点。但这会起作用。

于 2009-02-15T06:42:06.803 回答