我正在创建一个类似于向量的类。它使用自己的算法来确定数据的实际存储位置和方式。从用户的角度来看,它就像一个普通的矢量一样工作。
在内部,它尝试通过不多次存储重复值来节省内存。如果将相同的值多次推送到矢量上,它会使用索引进行一些奇特的舞蹈动作,但只存储实际值一次。
当重载operator []时,index参数转换为" real"索引,以便它可以访问数据实际存储的位置。
如果用户试图访问这样的元素:
int i = svec[8];
通过将8转换为" real"返回正确的元素。索引和访问正确的元素。
当用户尝试分配如下值时会出现问题:
svec[8] = 1;
值8将再次覆盖到"真实" operator[]()
返回索引和对元素的引用。但是,多个索引可能映射到该元素。如果我返回一个引用并允许它被更改,则会产生不希望的副作用,即更改其他索引的值。
如果我只是按值返回元素,则无法使用operator []分配值。
在operator[]()
内,我想知道一个操作是否计划更改元素的值,这样我就可以创建一个新元素,用索引做一些更奇特的舞蹈动作,并返回一个引用新元素。
这样的事情可能吗?如果没有,似乎我被迫按值返回,从而阻止用户使用[]修改值。
答案 0 :(得分: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 { ... }
没有开销,每个通用编译器都应该优化代理元素。
这个技巧甚至在vector<bool>
的STL中使用。请查看此更完整的示例。
答案 1 :(得分:0)
您可以将具有转换运算符的类返回给类型和赋值运算符,该运算符通知向量元素需要更改。