设计惰性向量:const 的问题

发布于 2024-07-13 12:06:26 字数 1185 浏览 7 评论 0原文

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

I wrote a little "lazy vector" class (or, delayed vector) which is supposed to look like a std::vector and usable wherever a std::vector is used, but it loads its elements "lazily", i.e. it will load element n (and possibly a few more) from disk whenever someone accesses element n. (The reason is that in my app, not all elements fit into memory.)

Here is this LazyVector class, but there is a problem with const member functions that use such a vector, see below.

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
};

As I said, there is a problem when a const member function asks for an element of the LazyVector. By nature of the LazyVector, accessing an element is not const, i.e. it will change the vector vec below, which is forbidden in this context. The foo member function must be const and cannot be changed. How can I solve this?

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 
  }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

三五鸿雁 2024-07-20 12:06:26

您可以在 LazyVector 类的实现中使用可变成员数据或 const_cast。 因此,您可以创建消费类所需的常量假象,而实际上并不需要常量。

You can either use mutable member data or const_cast in the implementation of your LazyVector class. Thus you can create the illusion of constness needed by your consuming class without actually being const.

顾北清歌寒 2024-07-20 12:06:26

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

Use the mutable keyword on the elems_ data member.

乖乖哒 2024-07-20 12:06:26

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 而不是指向的对象)。

The const operator is used to show that the object is logically const.
The fact that your data is on disk is neither here nor there your object is not changing state so you can delegate the work for actually holding the data to another object a cache (Where the data is stored is an implementation details and not part of the objects state).

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

Here data is a pointer (a smart pointer but still a pointer). As long as the pointer does not change you are not changing the cost-ness of the LazyVector. But you can still call non const methods on the object pointed at by data (remember it is the pointer that is const NOT the object pointed at).

醉殇 2024-07-20 12:06:26

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

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

可变的就是针对这种情况的。 使向量可变或添加包含某种缓存条目的可变缓存成员。

阅读 const 成员的语义是什么功能 安东尼·威廉姆斯的回答。

For such things, the mutable keyword is for. Put your cache as a mutable object into your class. That is because your cache seems to not change the logical content/state of your object (i.e the elements of your vector or the size of it do not change).

const methods do not state they don't physically change your object. They state that they won't change the abstract value of your object. Implementation details that are abstracted away may still be changed by const functions.

The mutable is for this kind of cases. Make your vector mutable or add a mutable cache member that contains some sort of cache entries.

Read the What are the semantics of a const member function answer by Anthony Williams.

森林散布 2024-07-20 12:06:26

elems_ 声明为 mutable

mutable std::vector; elems_;

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

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

std::vector; *mutable_elems_;

mutable_elems_(&elems_)

Declare elems_ as mutable:

mutable std::vector<T> elems_;

There's other stuff you can do, but that's the supported way of doing it.

Edit: Another way of doing this is to add another member and set it in the constructor:

std::vector<T> *mutable_elems_;

mutable_elems_(&elems_)

未央 2024-07-20 12:06:26

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

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

A crude way of doing this would be

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

I guess there will be better way of doing this. But this will work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文