运算符[] C++获取/设置

运算符[] C++获取/设置,c++,C++,我无法区分运算符[]的get和set之间的差异。我需要说明这些函数调用之间的区别 cout << data[5]; data[5] = 1; 我做错了什么?将为常量数据对象调用运算符[]的常量版本: const Data data; cout << data[5]; 解决方案是使用将延迟实际操作的代理对象: #include <vector> #include <iostream> template<typename T> str

我无法区分运算符[]的get和set之间的差异。我需要说明这些函数调用之间的区别

cout << data[5];
data[5] = 1;
我做错了什么?

将为常量数据对象调用运算符[]的常量版本:

const Data data;
cout << data[5];

解决方案是使用将延迟实际操作的代理对象:

#include <vector>
#include <iostream>

template<typename T>
struct MyArray {
    std::vector<T> data;
    MyArray(int size) : data(size) {}

    struct Deref {
        MyArray& a;
        int index;
        Deref(MyArray& a, int index) : a(a), index(index) {}

        operator T() {
            std::cout << "reading\n"; return a.data[index];
        }

        T& operator=(const T& other) {
            std::cout << "writing\n"; return a.data[index] = other;
        }
   };

   Deref operator[](int index) {
       return Deref(*this, index);
   }
};

int main(int argc, const char *argv[]) {
    MyArray<int> foo(3);
    foo[1] = 42;
    std::cout << "Value is " << foo[1] << "\n";
    return 0;
}
不能使用简单常量,因为您可能需要从非常量实例中读取,这就是您必须延迟操作的原因:赋值发生在访问之后,编译器不会告诉您该访问稍后是否将用作赋值目标

因此,在访问时,您只需存储已请求的索引,并等待知道是否正在进行读取或写入操作。通过提供从代理到T的隐式转换运算符,您知道何时发生读取操作,通过提供从T到T的赋值运算符,您知道何时发生写入操作。

常量版本意味着,如果调用它的对象是常量,则允许您调用该版本的[]运算符,只有那个版本

但如果对象不是常量,则可以调用[]运算符的两个版本,但编译器将选择非常量版本。换句话说,对于非常量对象,运算符的非常量版本可以充当setter或getter。这就是为什么在您的示例中两种情况下都调用相同的版本,因为您的数据对象不是const

您必须执行以下操作:

const Data& data_cref = data;
cout << data_cref[5];  // calls the const version of operator[]

Data& data_ref = data;
data_ref[5] = 1;       // calls the non-const version of operator[]

为了与下标的普通含义兼容,下标运算符通常返回对所获取元素的引用。通过返回引用,下标可以在赋值的任意一侧使用

因此,通常最好同时定义此运算符的常量和非常量版本。应用于对象时,下标应返回对const的引用,以便将其分配给返回的对象


--C++Primer,第五版

您可能需要查找代理对象,代理对象通常用于区分读写操作。有关此主题的详细讨论,请参阅中的第30项代理类,其中包括代理类可以提供给您的与用户定义转换相关的令人惊讶的陷阱。那材料很好。
const Data& data_cref = data;
cout << data_cref[5];  // calls the const version of operator[]

Data& data_ref = data;
data_ref[5] = 1;       // calls the non-const version of operator[]