2013-10-07 35 views
17

我无法区分运算符get和set之间的区别[]。我需要说明这些函数调用之间的区别。运算符[] C++获取/设置

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

我使用了它,并且我发现的答案仍然没有帮助。人们建议通过添加const使方法的签名不同。我这样做了,他们仍然都用同样的方法。

有我用过的签名:

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

我在做什么错?

+3

您可能想要查找*代理对象*,这通常用于区分读取和写入。 – templatetypedef

+0

请参见Scott Meyers [更有效的C++]中的第30项“代理类”(http://www.amazon.com/More-Effective-Improve-Programs-ebook/dp/B004VSMDNY/ref=la_B004BBEYYW_1_2?s=books&ie= UTF8&qid = 1381129998&sr = 1-2)进行广泛的讨论,包括代理类可以为您提供的令人惊讶的缺陷(与用户定义的转换有关)。该材料是[强制性阅读](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。 – TemplateRex

回答

16

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

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

简单const因为您可能需要从非常量实例中读取,所以无法使用该属性,这就是您必须延迟操作的原因:分配发生在“访问和编译器之后”之后告诉你访问是否将被用作分配目标。

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

0

const版本的广告operator[]将呼吁const数据对象:

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

const版本意味着如果在调用它的对象是const,你可以调用该版本的[]运营商,只有该版本。

但是,如果对象不是const,则可以调用[]运算符的两个版本,但编译器将选择非const版本。换句话说,对于非const对象,操作符的非const版本可以充当“setter”或“getter”。这就是为什么在你的例子中,在这两种情况下调用相同的版本,因为你的data对象不是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[] 
1

为了与标普通意义兼容,下标运算符通常返回到即取元素的引用。 通过返回引用,可以在任务的任一侧使用下标。

因此,定义该运算符的const和nonconst版本通常也是一个好主意。当应用于对象时,下标应该返回对const的引用,以便将其分配给返回的对象。

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