Reputation: 1843
When do you need to use an &
before the operator declaration?
Example:
class ClassName {
public:
// Some constructor here..
ClassName operator+(...)
ClassName operator*(...)
ClassName &operator+=(...) < has an &
ClassName operator==(...)
ClassName &operator<<(...) < has an &
private:
// Some member variables here..
}
When you want to distinguish a postfix and prefix i++
or ++i
you use an &
ClassName &operator++()
ClassName operator++(int)
But when do you use an &
for the other operator overload functions? Is there some kind of rule or has it something to do with the memory?
Upvotes: 5
Views: 2713
Reputation: 238311
When do you need to use an & before the operator declaration?
The & symbol declares the return type of the function to be a reference. More specifically, an lvalue reference. So, you use & when you want to return an lvalue reference, and don't use & when you want to return a non-reference.
So, when do you want to return a reference from an operator overload? A concise rule of thumb is that you should return a reference if the built-in operator for non class types is an lvalue expression, and return a non-reference when the built-in operator is an rvalue expression. There are exceptions to this. For example, sometimes you cannot return a reference. Perhaps you need to return some sort of wrapper object that behaves like a reference; such wrappers are typically returned by value.
Assignment operators, including the compound assignment operators such as +=
conventionally return a reference to *this
.
Postfix operator conventionally returns the previous value. As such, it cannot return a reference to *this
, which contains the current value. Prefix operator does return the current value, so it can return a reference. The prefix increment of a non-class object is an lvalue expression, so returning an lvalue (i.e. a reference) from the operator overload is a good convention.
Upvotes: 7
Reputation: 385106
tl;dr: Same as with any function. Do you return by value, or by reference?
It might be clearer if you align your ampersand to the left (which has no semantic effect, just like with char* str
vs char *str
):
ClassName& operator++()
ClassName operator++(int)
So the choice depends on whether you want to return a reference to the existing object:
ClassName& operator++()
{
this->someMember += 1;
return *this;
}
…or a nice new one:
ClassName operator++(int)
{
// Post-fix operator so we have to return the "old" unmodified version
ClassName old = *this;
this->someMember += 1;
return old;
}
In the first case, returning by value would be confusing to the user of your ++
, because:
++
would not affect the original object.In the second case, returning by reference would be bad because:
Upvotes: 10