for example,
in this one,
I 'm not very understand about the this pointer,
this question is not about operator+ overload,
is about the this pointer, and its relation between the class,
*this pointer point to what thing?
thank u very much!
class Integer {
int i;
public:
Integer(int ii): i(ii) { }
const Integer operator+(const Integer& rv) const {
cout<<"operator+"<<endl;
}
Integer&
operator+=(const Integer& rv) {
i += rv.i;
return *this;
}
}
thisidentifies a special type of pointer.IF you create an object named x of class A, and class A has a nonstatic member function f(). If you call the function x.f(), the keyword this in the body of f() stores the address of x. You cannot declare the this pointer or make assignments to it.
Basically this pointer is passed as a hidden argument to all nonstatic member function calls and is available as a local variable within the body of all nonstatic functions.
operator+= needs to return a reference to the current object (after it has been incremented) so that you can still write code such as
// UGLY CODE, ONLY TO ILLUSTRATE A POINT
Integer x, y;
x = (y += 10) + 1;
This form of the operator (taking a const reference, returning a reference) is also called the canonical form.
Where do you get the reference to return? You have this, which points to the current object, but you cannot return a pointer. So you dereference the pointer with operator* and return the result:
return *this;
Related
I've got this code snippet but I am not quite sure why I should put an asterisk before "this" when I am overloading the += operator. "this" is a pointer. Does the asterisk dereference the "this" keyword? If yes, then what does it mean? My guess is that since "this" is a pointer to the object, by dereferencing it I am getting the address of the memory where the object is, so the compiler implicitly saves the address in a temp and I am returning the temp as a reference. Is my understanding correct?
#include <iostream>
class Account {
public:
explicit Account(double b) : balance(b) {}
Account& operator+=(double b) {
balance += b;
return *this;
}
friend Account& operator+=(Account& a, Account& b);
friend std::ostream& operator<<(std::ostream& os, const Account& a);
private:
double balance;
};
Does the asterisk dereference the "this" keyword?
Yes.
The keyword this is a rvalue(until C++11) prvalue(since C++11) expression whose value is the address of the implicit object parameter (object on which the non-static member function is being called).
That being the case, when dereferencing it you will be returning the object and not its address, as a normal pointer.
My guess is that since "this" is a pointer to the object, by dereferencing it I am getting the address of the memory where the object is...
It's the opposite, had you not dereferenced it you would be returning the address, by dereferencing it you're returning the object, i.e. the value stored in that address.
I've got this code snippet but I am not quite sure why I should put an asterisk before "this" when I am overloading the += operator.
Given the above explanations and knowing the += operator is used to add and assign values, why would you not dereference this and return an address? It wouldn't make sense.
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).
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.
In my C++ class they were discussing how to create an assignment operator. At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to. Why does it return a reference? If "this" is being dereferenced, shouldn't it just return the object?
A function returns a reference if its declaration (i.e. its signature) tells so.
So (assuming a class Foo) if a function is declarated
Foo fun();
then it returns a value (with copying, etc..)
But if it is declared as
Foo& fun();
or as
const Foo& fun();
a reference is returned.
The statement return *this; don't define by itself if a reference or a value is returned.
It returns the current instance of the type MyClass you are in. It's returned as reference because the assignment operator was explicitly told to return a reference.
MyClass& operator = (MyClass& other) { return *this; }
Note the & after MyClass as the return value. A reference is returned.
Unless the & weren't there right before operator, the instance would be returned by value.
The expression *this
At the end of the assignment was the line "return *this," which they said returned a reference to the object that "this" points to
They were wrong.
Why does it return a reference?
It doesn't.
If "this" is being dereferenced, shouldn't it just return the object?
Yes!
Dereferencing a pointer yields an lvalue. That means that the result of *this is the actual object that this points to. It's not a reference, but it's not a copy either.
[C++11: 5.3.1/1]: The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.” [..]
It can be hard to conceptualise, since you can never do this yourself in code; it's just a feature of the * operator for native pointers, and has been since C.
Returning from operator=
Because you can't do it yourself, conventionally you'd bind that lvalue expression to a reference in order to use it in different contexts. For example, the expression *this in return *this gets bound to the return type of the function that you're returning from; in this case, an assignment operator.
Now, we could have the assignment operator return by value in which case an object copy would be made from the lvalue that comes from *this; however, for an assignment operator we usually return by reference so that we avoid an almost-certainly needless copy, and can perform chaining:
Type a, b, c;
c = b = a;
It's a convention with benefits, and no downsides. Can you think of a situation when you'd want op= to return by value?
Every dereferenced pointer is a reference to its pointee, else you'd 'loose' the pointee you're pointing to.
Invoke method twice on the same object, using a pointer and a reference:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass& objRef = *objPtr;
objRef.doSomething();
Invoke method on distinct objects; original and copy:
MyClass* objPtr = .... ;
objPtr->doSomething();
MyClass objCopy = *objPtr; //here, the reference is passed to the (implicit or implemented) copy constructor if possible, else a compile time error occurs.
objCopy.doSomething();
That means, if you return a reference from an operator method which has MyClass (rvalue) instead of MyClass& (lvalue) as return type, a copy of *this (MyClass&) is created by reference (leaving aside return value optimizations and rvalue references).
This is useful for non modifying const methods such as + and - which have a new value as result while leaving the object on which this method was invoked unmodified.
Operators like += and your assignment operator modify the object inplace by convention and should therefore return a reference to allow expressions like primitive types support it, since a temporary copy may vanish and cause unexpected results:
Consider this expression:
int i = 4;
int r = (i += 3) <<= 2;
The result r is 28 (added and shifted inplace).
What is the value of i? 28 too, what else.
But what if hypothetically int::operator+= would return a copy of itself instead of a reference to itself?
The result r would be 28 too.
But the value of i?
It would be 7, since the inplace left shift was applied to a temporary int returned from the addition which gets assigned to r after that.
Continuing the assumption, the error may have the same effect (except for the value in i) as this expression:
int r = (i + 3) <<= 2;
But luckily, the compiler will complain, that he doesn't have an lvalue reference from (i + 3) to do the shift/assignment operation.
But play with this:
class Int
{
private:
int val;
public:
Int(int val) :
val(val)
{
}
Int operator+(const Int& other)const
{
return val + other.val;
}
Int operator+(int prim)const
{
return val + prim;
}
Int& operator+=(const Int& other)
{
val += other.val;
return *this;
}
//Error here, Int& would be correct
Int operator+=(int prim)
{
val += prim;
return *this;
}
Int operator<<(const Int& other)const
{
return val << other.val;
}
Int operator<<(int prim)const
{
return val << prim;
}
Int& operator<<=(const Int& other)
{
val <<= other.val;
return *this;
}
Int& operator<<=(int prim)
{
val <<= prim;
return *this;
}
operator int()const{
return val;
}
};
int main()
{
Int i = 4;
Int r = (i += 3) <<= 2;
cout << i;
return 0;
}
In C++ the * always means a value, in fact you can look to en English interpretation for these operators as follows:
&: the address of
*: the value of
So when you say &x it means "the address of x" and when you say *x it means "the value that x points to". So *this will always return a value.
Just be sure that the function itself that the hosts the returning is not a reference function. Please remember that in C++ you can create functions with the & or the * operators as well.
this is an assignment operator. &rhs != this is confusing. my questions: rhs is a reference of Message type. What does &rhs mean? what does & do (a memory address of a reference?)?
Another question is about return *this . since we want a reference to type Message, but *this is a Message typed object, right? How can we return an object to a reference?
Message& Message::operator=(const Message &rhs)
{
if (&rhs != this)
{
some functions;
}
return *this;
}
&rhs means address of the object which reference is referecing to.
Message a;
const Message &rhs = a;
if (&rhs == &a) std::cout << "true" << std::endl;
This is will print true.
A reference is not a different object; it is just a syntactic sugar of pointer, which points to the same object whose reference it is. So when you write return this, it returns a pointer to the object, but if you write return *this, it returns either a copy of the object, or reference to the object, depending on the return type. If the return type is Message &, then you tell the compiler that "don't make a copy and instead return the same object". Now the same object is nothing but a reference. A reference of an object can be made anytime. For example, see the declaration of rhs above; it is const Message & rhs = a, since the targer type is mentioned as reference type, you're making a reference rhs of the object a. It is that simple.
Besides Nawaz's great answer, I want to point out that you have to be careful about returning a reference to a local variable which will go out of scope after function return. So avoid returning a reference like this:
string& foo()
{
string result = "abc";
return result;
}
which causes the following compiler warning:
reference to local variable result returned
A reference is just an alias to an object. References are formed by request of the function that is called; they are not (necessarily) part of an object's type. This is probably already familiar to you, but consider this:
void f1(int a) { ++a; }
void f2(int & a { ++a; }
int main()
{
int x = 5;
f1(x);
f2(x);
}
Surely you know the difference between the two functions. But note that x is always just an object of type int. Whether it is passed by reference or by value is not a property of x, but rather of the function.
The same goes for return types:
int q;
int g1() { return q; }
int & g2() { return q; }
int main()
{
++g2();
++g1(); // error
}
Again, q is just an object. Whether return q; returns it by value or by reference is not a property of q, but of the function. g1 makes a copy of q, while g2 returns a reference to the actual q object (which we can increment). (The return value of g1 cannot be incremented, precisely because it doesn't have a permanent existence and this would be meaningless (technially, the expression is an rvalue).)
So in you example, return *this; returns a reference to the object itself. That has nothing to do with this, but it has everything to do with the fact that the return type of the function is Message&.