简体   繁体   中英

How can std::string operator[] return a reference rather than the character?

I was going through the book Effective C++ by Scott Meyers and while reading Item 3 - Use const whenever possible found this example quite misleading.

My question is - How can an array access return a reference at the interested index rather than the item at that index.

Also attaching the program for reference here that I executed to confirm that this is happening

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

I got the corresponding output

Before calling operator overloading Hello
After calling operator overloading Iello

Is the observed behaviour something specific to operator overloading?

My question is - How can an array access return a reference at the interested index rather than the item at that index.

It isn't an array access. You are calling the following overload of std::string when you do text[position] .

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

which returns a reference to a character in the specified location of the string, which effectively is a container of chars. This is similar to how other containers work, such as std::map or std::vector . This behaviour is made possible by overloading the indexing operator for a class. It would otherwise be undefined since indexing is only possible on pointers/arrays or classes with the overload implemented.

With that said, it should be kept in mind that array indexing is effectively a pointer dereference, which means it can be bound to a reference in the same way and lead to the same results, like below (try it out). That is because carray[i] is equivalent to *(carray + i) which is one way to tell the compiler it is okay to implicitly cast your pointer to a reference.

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

There are good reasons for the indexing operator to be implemented as such. It effectively allows you to treat std::string like you would a char[] ; you can assign any given index a value as well as access any given index to get a value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM