I am writing C++ code, and ran into a case where I wish to overload the square bracket operator for my class. From various sources, I find that you usually make two methods to do this, one with the const
keyword, and one without the const
keyword, but with an ampersand (&
) before the method name. An example is given below.
int MyClass::operator[](unsigned int i) const {
return this->values[i];
}
int & MyClass::operator[](unsigned int i) {
return this->values[i];
}
My questions are as follows:
const
keyword, and one without it?&
) in my second method do?Why do I have two methods, one with the const keyword, and one without it?
The const
keyword sets a constraint that prevents the function from modifying the object. For example, if you use the const
keyword in a setter, you'll get a compiler error.
So the first function won't allow any modification on the object and in this case it will return a copy of the accessed element. The first function is a getter in disguise, it is a read only access, so to speak.
What does the ampersand (&) in my second method do?
The second function, instead, has the ampersand after the type, which means that it will return a reference of the returned value and not a copy of it. The returned value is part of the object, so returning a reference to it implies a potential modification and the const
keyword wouldn't allow it.
So this second function is a setter in disguise, it is a write access.
Why can I set a value at a given index using square brackets, when none of my methods are setters, and which of these two methods is invoked when I set a value?
As we've seen, the second function acts like a setter. When you use it, the returned value is a reference to the real element inside your object, and is valid for assignation (we call it a lvalue, more about them here).
The point of this overload is: whenever you use the operators for a read operation (right side of the assignation or as a parameter) the first function will be called. If you use it for a write operation, it will be the second. In fact, this is how the same operator works for the STL containers you are probably using in your code.