std :: string operator []如何返回引用而不是字符?

时间:2015-03-21 18:04:56

标签: c++ operator-overloading

我正在阅读Scott Meyers撰写的有效C ++一书,在阅读第3项时 - 尽可能使用const,这个例子很容易产生误导。

我的问题是 - 数组访问如何在感兴趣的索引处返回引用而不是该索引处的项目。

另外附上我执行的参考程序以确认发生了这种情况

#include <iostream>
#include <string>

using namespace std;

class TextBlock
{
    public:
        explicit TextBlock(const std::string str) : text(str) {}
        const char& operator[](std::size_t position) const { return text[position]; }
        char& operator[](std::size_t position) { return text[position]; }

        std::string get_text() { return text; }

    private:
        std::string text;
};

int main()
{
    TextBlock tb("Hello");
    cout << "Before calling operator overloading " << tb.get_text() << "\n";
    tb[0] = 'I';
    cout << "After calling operator overloading " << tb.get_text() << "\n";
    return 0;
}

我得到了相应的输出

Before calling operator overloading Hello
After calling operator overloading Iello

观察到的行为是否特定于运算符重载?

1 个答案:

答案 0 :(得分:2)

  

我的问题是 - 数组访问如何在感兴趣的索引处返回引用而不是该索引处的项目。

不是数组访问权限。当您执行std::string时,您正在调用text[position]的以下重载。

char& std::string::operator [] ( std::size_t index ) ;

引用返回给字符串指定位置的字符,该字符实际上是字符的容器。这类似于其他容器的工作方式,例如std::mapstd::vector。通过重载类的索引运算符可以实现此行为。否则它将是未定义的,因为只能在指针/数组或实现重载的类上进行索引。

说到这一点,应该记住,数组索引实际上是一个指针取消引用,这意味着它可以以相同的方式绑定到引用并导致相同的结果,如下所示(试一试)。这是因为carray[i]等同于*(carray + i),这是告诉编译器可以隐式地将指针强制转换为引用的一种方法。

char& operator [] ( std::size_t i ) { return carray[i]; }
...
char carray[10];

有充分理由将索引运算符实现为这样。它有效地允许您像std::string一样对待char[];您可以为任何给定索引分配值,也可以访问任何给定索引以获取值。