I've seen many tutorials and tried to find the answer on stackoverflow but with no success.
What I'm not sure of is; is there some praxis when to return by value or by reference, when overloading an operator?
For e.g.
Class &operator+(){
Class obj;
//...
return obj;
}
or the same thing but by value
Class operator+(){
Class obj;
//...
return obj;
}
And I'd like to mention, I've noticed that in almost 90% of cases when returning the same object (*this), is being referenced on the same object returned. Could someone explain why is that so, as well?
The first option of returning from operator+ by by reference is wrong, because you are returning local object by reference, but the local object ceases to exist after the operator function body ends. Generally:
Mutating operators like += or -= return by reference, because they return the mutated object itself (by: return *this;)
Normal operators like + or - should return by value, because a new object needs to be constructed to hold the result.
... is there some praxis when to return by value or by reference, when overloading operator?
Yes, there are some canonical forms found here. They don't all have the same form - they vary by operator. The general advice is to follow the semantics of the built-in types. As with all functions, general rules still apply, such as not returning references to local variables (as shown in the OP).
E.g. (found in the link above) given the addition operator of the question;
class X
{
public:
X& operator+=(const X& rhs) // compound assignment (does not need to be a member,
{ // but often is, to modify the private members)
/* addition of rhs to *this takes place here */
return *this; // return the result by reference
}
// friends defined inside class body are inline and are hidden from non-ADL lookup
friend X operator+(X lhs, // passing lhs by value helps optimize chained a+b+c
const X& rhs) // otherwise, both parameters may be const references
{
lhs += rhs; // reuse compound assignment
return lhs; // return the result by value (uses move constructor)
}
};
The operator+ is a non-member method (often as a friend) and returns by value - this corresponds to the semantics of the built in types. Similarly, the operator+= is a member method and returns by reference (an updated version of *this).
... when returning the same object (*this), is being referenced on the same object returned. Could someone explain why is that so, as well?
If the return type is by-value (X operator+), then return *this; means that a copy of the current object (what is pointed to by this) is made and returned.
If the return type is by-reference (X& operator+), then return *this; means that a reference to the current object (what is pointed to by this) is returned (i.e. not a copy).
Related
For the sake of completeness, I want to provide me with a trivial unary + operator as well.
The unary operators should be immutable, I think. If I make operator-() return a copy of the negated object, a statement -obj=other; (both obj and other are objects of type Complex) will not compile. However, if I make operator+() return the object itself, another statement +obj=other; will compile.
The problem is I cannot use const in the following snippet. What does the error mean?
Complex& operator+() const
{
return *this;
}
Complete Code
class Complex
{
private:
double re;
double im;
public:
// others are intentionally removed for the sake of simplicity
Complex operator-() const
{
return Complex{-re,-im};
}
Complex& operator+() const
{
return *this;
}
}
You operator is marked const thus the *this is Complex const &. Your return type strips the const.
By declaring the function const , you in fact give a promise that this operation won't change the object's state .
In other words , this is now a const pointer ( aka a pointer to constant data ) , and thus by dereferencing it you get a const Complex& , something which is dropped when you assign that value to a non-const reference and thus the error .
You have to change your code to this:
const Complex& operator+() const {
return *this;
}
When declaring a method with const, not only are you promising you won't touch any of the internal state of the object, you also promise that you will not return anything that can be used to change the internal state of the object
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?
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:
there was an unnecessary copy, and
further operations on the result of ++ would not affect the original object.
In the second case, returning by reference would be bad because:
it would be a dangling reference to a local variable.
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.
I am new to C++. I need some help understanding this code snippet.
Queue & operator=(const Queue &rhs)
{
front = rhs.front;
nWaiting = rhs.nWaiting;
for (int i = front, j = 0; j < nWaiting; j++)
{
elements[i] = rhs.elements[i];
i = (i + 1) % 100;
}
return *this;
}
I am unable to understand why there is an '&' before operator in the code and how does this work along with *this.
I understand operator overloading. For eg. the code below for addition operation overloading. However I don't understand why '&' is required for assignment operator (=) overloading.
V3 operator* (const double factor, const V3 &b)
{
return (b * factor);
}
The reference means that avoid copying the object. As a result, it will return a reference to the same object. Moreover, it will provide lvalue as a result. And if you think about it, that's what you want to happen when the assignment operator is used.
Every object in C++ has access to its own address through this pointer.
That means that the you return the object itself.
If your question is why we use *this instead of this, then this happens because you need to dereference the pointer first, since the return type is a reference (and not a pointer for example).
The & means the operator returns a reference (the original object), instead of a value (a copy of the object). This avoids unnecessary copying. this is a pointer to the object itself which the operator is called on, so return *this means return a reference to the object on the left side of the =.
This allows for the operator to be chained, like a = b = 1. This assigns 1 to b first, and a reference to b is returned. The value of b then gets assigned to a. So a and b both are 1.
The operator could be fine without any return value, however it is common to enable chaining as in
c = (a = b);
This will assign b to a and then assign the return value of the operator= call to c. As you dont want to make a unneccesary copy you return a reference to the object itself aka *this. Actually avoiding a copy is not the only reason for using a reference, but if you consider
(d = e) = f;
then this will only work as expected (first assigning e to d and then assigning f to d) if operator= returns a non-const (!) reference.
Note that operator* is different, because it is not supposed to modify the object it is invoked on but rather it returns a new instance (hence no & in the return of operator*).
MyObject& MyObject::operator++(int)
{
MyObject e;
e.setVector(this->vector);
...
return &e;
}
invalid initialization of non-const reference of type 'MyObject&' from an rvalue of type 'MyObject*'
return &e;
^
I am not sure what it's saying. Is it saying that e is a pointer, because it's not a pointer. Also, if you'd make a pointer to the address of e, it would get wiped out at the end of the bracket and the pointer would be lost.
Your return type is MyObject&, a reference to a (non-temporary) MyObject object. However, your return expression has a type of MyObject*, because you are getting the address of e.
return &e;
^
Still, your operator++, which is a postfix increment operator due to the dummy int argument, is poorly defined. In accordance to https://stackoverflow.com/a/4421719/1619294, it should be defined more or less as
MyObject MyObject::operator++(int)
{
MyObject e;
e.setVector(this->vector);
...
return e;
}
without the reference in the return type.
You're correct that e is not a pointer, but &e very much is a pointer.
I'm reasonably certain that returning a reference to a stack variable that will be out of scope before you can use it is also not such a good idea.
The general way to implement postfix operator++ is to save the current value to return it, and modify *this with the prefix variant, such as:
Type& Type::operator++ () { // ++x
this->addOne(); // whatever you need to do to increment
return *this;
}
Type Type::operator++ (int) { // x++
Type retval (*this);
++(*this);
return retval;
}
Especially note the fact that the prefix variant returns a reference to the current object (after incrementing) while the postfix variant returns a non-reference copy of the original object (before incrementing).
That's covered in the C++ standard. In C++11 13.6 Built-in operators /3:
For every pair (T, VQ), where T is an arithmetic type, and VQ is either volatile or empty, there exist candidate operator functions of the form:
VQ T & operator++(VQ T &);
T operator++(VQ T &, int);
If, for some reason, you can't use the constructor to copy the object, you can still do it the way you have it (creating a local e and setting its vector) - you just have to ensure you return e (technically a copy of e) rather than &e.
Change return &e; to return e;. In the same way that a function like
void Func(int &a);
isn't called with Func(&some_int) you don't need the & in the return statement. &e takes the location of e and is of type MyObject*.
Also note, MyObject& is a reference to the object, not a copy. You are returning a reference to e, which will be destroyed when the function finishes and as such will be invalid when you next make use of it.
Is it safe to write our own copy constructor always during operator overloading ?
Complex Complex::operator+(const Complex& other)
{
Complex local ;
local.result_real = real + other.real;
local.result_imaginary = imag + other.imag;
return local ;
}
Most of the times i have seen the above format , instead of returning it as reference .
Can we take thumb rule like
1- Always pass the function parameter by reference .
2- Always return the object by reference .
Is there any special case in operator overloading where we have to return the object by value only ?
Can we take thumb rule like 1- Always pass the function parameter by reference . 2- Always return the object by reference .
No, not really. Even if you found a way to return a non-dangling reference, an operation such as addition should not return a reference, since this does not make sense. a+b should return a new object, while for a+=b it does make sense to return a reference to the LHS.
Concerning passing an argument by reference, there is no rule of thumb either. Consider this:
A operator+(const A& lhs, const A& rhs)
{
A tmp = lhs; // explicitly make a copy
return tmp += rhs;
}
and this:
A operator+(A lhs, const A& rhs)
{
return lhs += rhs;
}
The second version passes one argument by value, resulting in simpler code and giving the compiler more opportunities to elide temporary copies.
For some operators you should return a reference, for others you should not, and still others return other types completely (like the comparison operators).
In your case you should not. Especially since you will then return a reference to a local variable which will not be valid when the function returns.