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.
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*).
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).
iarray<T>& operator = (iarray<T>& v)
Why the return type is iarray<T>& not iarray<T> ?
UPDATE
Can someone elaborate in great detail why iarray<T> const &v ?
Because you don't want to return a copy of the array just for the sake of chaining. Returning a reference is a better option as it doesn't result in a copy being constructed.
Because then you can chain them efficiently, eg.
a = b = c;
See the C++ FAQ.
Why the return type is iarray& not iarray ?
Because the result of an assignment is a reference to what just got assigned. For example, the result of a = b should be a reference to a so you can chain them together like in c = a = b; which is effectively a = b; c = a;. (Yes, people like doing this on rare occasions; no, I don't know why it's such a hardship to break it into two lines.) Thus your code should look like:
iarray<T>& iarray<T>::operator = (const iarray<T>& v)
{
// ... copy `v`'s state over this object's ...
return *this;
}
Can someone elaborate in great detail why iarray const &v ?
Because an assignment operation has no business changing the right-hand side; it is unexpected behavior. If you have some funky thing in your object that needs to change, like a reference count, then you should prefer declaring that one part mutable over disallowing const right-hand side expressions. You can pass a non-const value in for a const parameter, but the reverse is not true.