2

我正在创建一个类似于向量的类。它使用自己的算法来确定数据的实际存储位置和方式。从用户的角度来看,它就像法线向量一样工作。

在内部,它尝试通过不多次存储重复值来节省内存。如果多次将相同的值推送到向量上,它会使用索引执行一些花哨的舞蹈动作,但只存储一次实际值。

重载 operator[] 时,索引参数将转换为“真实”索引,以便它可以访问实际存储数据的位置。

如果用户尝试访问这样的元素:

int i = svec[8];

通过将 8 转换为“真实”索引并访问正确的元素来返回正确的元素。

当用户尝试像这样分配值时,问题就出现了:

svec[8] = 1;

值 8 将再次被“真实”索引覆盖,并且对元素的引用由operator[](). 但是,多个索引可能映射到该元素。如果我返回一个引用并允许对其进行更改,则会产生更改其他索引值的不良副作用。

如果我只是按值返回元素,您将无法使用 operator[] 分配值。

operator[]()中,我想知道一个操作是否计划更改元素的值,以便我可以创建一个新元素,使用索引做一些更花哨的舞蹈动作,并返回对新元素的引用。

这样的事情可能吗?如果不是,似乎我被迫按值返回,从而阻止用户使用 [] 修改值。

4

2 回答 2

3

如果这个类有一个方法change_element并且每个人都在更改时调用这个函数,那将很容易,不是吗?

template <typename T>
struct my_vec {
  T& change_element(int index, T new_value)
  { ... }
};

现在,我们的想法是返回一个代理类,operator[]它会为您完成这项工作。

  // inside my_vec:
  struct proxy {
    my_vec *vec;
    int index;

    T& operator=(T o)
    { return vec->change_element(index, std::move(o)); }

    operator T() const { return (*const_cast<my_vec const*>(vec))[index]; }
  };

  proxy operator[](int i) { return proxy{this, i}; }
  T const& operator[](int i) const { ... }

没有开销,每个常见的编译器都应该优化代理元素。

这个技巧甚至在 STL 中被vector<bool>. 查看这个以获得更完整的示例。

于 2012-11-24T14:23:07.967 回答
0

您可以返回一个类,该类具有类型的转换运算符和一个通知向量元素需要更改的赋值运算符。

于 2012-11-24T14:16:25.880 回答