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

Operator[] C++ Get/Set

本文关键字:设置 获取 C++ 运算符      更新时间:2023-10-16

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

cout << data[5];
data[5] = 1;

用谷歌搜索了一下,我找到的答案仍然没有帮助。人们建议通过添加 const 来使方法的签名不同。我这样做了,他们仍然使用相同的方法。

有我用过的签名:

const T& operator[](unsigned int index) const;
T& operator[](unsigned int index);

我做错了什么?

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

#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 << "readingn"; return a.data[index];
        }
        T& operator=(const T& other) {
            std::cout << "writingn"; 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;
}

不能使用简单的 const -ness,因为您可能需要从非 const 实例读取,这就是您必须延迟操作的原因:赋值发生在"访问之后",编译器不会告诉您访问以后是否会用作赋值的目标。

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

const 版本意味着如果调用它的对象是 const ,则允许您调用该版本的 [] 运算符,并且只能调用该版本。

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

您必须执行以下操作:

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 和非 const 版本通常也是一个好主意。当应用于对象时,下标应返回对 const 的引用,以便将其分配给返回的对象。

----C++ 入门,第五版

const数据

对象将调用operator[] const版本:

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