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.