Role of " * " in operator overloading - c++

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.

Related

Why do we return *this in asignment operator and generally (and not &this) when we want to return a reference to the object?

I'm learning C++ and pointers and I thought I understood pointers until I saw this.
On one side the asterix(*) operator is dereferecing, which means it returns the value in the address the value is pointing to, and that the ampersand (&) operator is the opposite, and returns the address of where the value is stored in memory.
Reading now about assignment overloading, it says "we return *this because we want to return a reference to the object". Though from what I read *this actually returns the value of this, and actually &this logically should be returned if we want to return a reference to the object.
How does this add up? I guess I'm missing something here because I didn't find this question asked elsewhere, but the explanation seems like the complete opposite of what should be, regarding the logic of * to dereference, & get a reference.
For example here:
struct A {
A& operator=(const A&) {
cout << "A::operator=(const A&)" << endl;
return *this;
}
};
this is a pointer that keeps the address of the current object. So dereferencing the pointer like *this you will get the lvalue of the current object itself. And the return type of the copy assignment operator of the presented class is A&. So returning the expression *this you are returning a reference to the current object.
According to the C++ 17 Standard (8.1.2 This)
1 The keyword this names a pointer to the object for which a
non-static member function (12.2.2.1) is invoked or a non-static data
member’s initializer (12.2) is evaluated.
Consider the following code snippet as an simplified example.
int x = 10;
int *this_x = &x;
Now to return a reference to the object you need to use the expression *this_x as for example
std::cout << *this_x << '\n';
& has multiple meanings depending on the context. In C and used alone, I can either be a bitwise AND operator or the address of something referenced by a symbol.
In C++, after a type name, it also means that what follows is a reference to an object of this type.
This means that is you enter :
int a = 0;
int & b = a;
… b will become de facto an alias of a.
In your example, operator= is made to return an object of type A (not a pointer onto it). This will be seen this way by uppers functions, but what will actually be returned is an existing object, more specifically the instance of the class of which this member function has been called.
Yes, *this is (the value of?) the current object. But the pointer to the current object is this, not &this.
&this, if it was legal, would be a pointer-to-pointer to the current object. But it's illegal, since this (the pointer itself) is a temporary object, and you can't take addresses of those with &.
It would make more sense to ask why we don't do return this;.
The answer is: forming a pointer requires &, but forming a reference doesn't. Compare:
int x = 42;
int *ptr = &x;
int &ref = x;
So, similarly:
int *f1() return {return &x;}
int &f1() return {return x;}
A simple mnemonic you can use is that the * and & operators match the type syntax of the thing you're converting from, not the thing you're converting to:
* converts a foo* to a foo&
& converts a foo& to a foo*
In expressions, there's no meaningful difference between foo and foo&, so I could have said that * converts foo* to foo, but the version above is easier to remember.
C++ inherited its type syntax from C, and C type syntax named types after the expression syntax for using them, not the syntax for creating them. Arrays are written foo x[...] because you use them by accessing an element, and pointers are written foo *x because you use them by dereferencing them. Pointers to arrays are written foo (*x)[...] because you use them by dereferencing them and then accessing an element, while arrays of pointers are written foo *x[...] because you use them by accessing an element and then dereferencing it. People don't like the syntax, but it's consistent.
References were added later, and break the consistency, because there isn't any syntax for using a reference that differs from using the referenced object "directly". As a result, you shouldn't try to make sense of the type syntax for references. It just is.
The reason this is a pointer is also purely historical: this was added to C++ before references were. But since it is a pointer, and you need a reference, you have to use * to get rid of the *.

Why can delete operator be used in const context?

This question is different from:
Is a destructor considered a const function?
new-expression and delete-expression on const reference and const pointer
Deleting a pointer to const (T const*)
I wrote a class Test like this.
class Test {
private:
int *p;
public:
//constructor
Test(int i) {
p = new int(i);
}
Test & operator = (const Test &rhs) {
delete p;
p = new int(*(rhs.p));
return *this;
}
};
When the parameter rhs of the operator function is itself (i.e. Test t(3); t = t;), delete p; also changes the pointer p of rhs. Why is this allowed?
C++ standard (N3092, "3.7.4.2 Deallocation functions") says
If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.
(Note: delete-expression internally calls a deallocation function. So this excerpt is related with delete operator.)
So I think delete p; may change the member p of rhs though rhs is a const reference.
Someone may insist that "to render a pointer invalid is not to change the value of a pointer" but I don't find such a statement in the standard. I doubt there is a possibility that the address pointed by rhs's p has been changed after delete p; in operator =(*).
(*): Whether or not this situation can be reproduced on popular compilers doesn't matter. I want a theoretical guarantee.
Supplement:
I've changed delete p; to delete rhs.p;, but it still works. Why?
Full code here:
#include <iostream>
class Test {
private:
int *p;
//print the address of a pointer
void print_address() const {
std::cout << "p: " << p << "\n";
}
public:
//constructor
Test(int i) {
p = new int(i);
}
Test & operator = (const Test &rhs) {
print_address(); //=> output1
delete rhs.p;
print_address(); //=> output2
p = new int(*(rhs.p));
return *this;
}
};
int main() {
Test t(3);
t = t;
}
In this case, it is guaranteed that p is invalidated. But who guarantees invalidate != (change the value)? i.e. Does the standard guarantee that output1 and output2 are the same?
So I think delete p; may change the member p of rhs though rhs is a const reference.
No. delete p; doesn't change p. Invalidation is not modification.
Regardless, having a const reference to an object (rhs) does not by any means prevent the referred object form being modified. It merely prevents modification through the const reference. In this case we access the object through this which happens to be a pointer to non-const, so modification is allowed.
Someone may insist that "to render a pointer invalid is not to change the value of a pointer" but I don't find such a statement in the standard.
The behaviour of delete expression is specified in [expr.delete]. Nowhere in that section does it mention that the operand is modified.
Becoming invalid is specified like this:
[basic.compound]
... A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration ...
Note that it is the value that becomes invalid. The pointer still has the same value because the pointer was not modified. The value that the pointer had and still has is simply a value that no longer points to an object - it is invalid.
Supplement: I've changed delete p; to delete rhs.p;, but it still works. Why?
Answer 2. From previous question no longer applies, but answer 1. does. delete rhs.p; does not modify rhs.p.
Calling delete on a member pointer frees the memory the pointer points to but does not change the pointer itself. Thus, it does not change the bitwise contents of the object, thus it can be done in a const member.
C++ only cares about bitwise const (of the object the method is invoked on). Not logical const. If no bits in the object change, then all is well - const wise - as far as the C++ language is concerned. It does not matter whether the logical behaviour of the object is changed (for example by changing something member pointers point to). That's not what the compiler checks for.

Why do we use the reference operator twice?

My question refers to pointers with classes and the keyword this.
class class1 {
public:
bool isitme(class1& temp){
if(this == &temp)
return true;
else return false;
}
};
int main () {
class1 c3;
class1* c2 = &c3;
if(c3.isitme(*c2))
cout << "c3 == c2"; //it is returning that
system("pause");
}
The code above is working, but what I do not understand is why it works only when bool isitme(class1& temp) and if(this == &temp) are in the same function isitme().
I mean, we already read the block of memory class1& temp of temp in the class parameters and should be able to compare that block of memory with the keyword this. Why is the function only true when I double get the reference (this == &temp)?
Thanks
this is a pointer, whereas temp is a reference. When you write &temp in your if statement, you are taking the address of temp. This converts it to a pointer that can then be compared to this.
Do not confuse reference declarations with use of the address-of operator. When & identifier is preceded by a type, such as int or char, then identifier is declared as a reference to the type. When & identifier is not preceded by a type, the usage is that of the address-of operator.
Taken from: http://msdn.microsoft.com/en-us/library/w7049scy(v=vs.71).aspx
It's been a while since c/c++ days, but let me take a stab at this...
You're not using the reference operator twice. When you specify class1& you're only specifying the type of the parameter (the type is "reference of type class1"), not actually doing anything to temp. Later you actually dereference the parameter with &temp. It's only the second appearance of the ampersand that actually is a reference operator.
The & operator within the method declaration simply means that the object passed should not be copied, but rather point to the same location as the object passed to it (it's a reference). The & operator in if(this == &temp) is needed to actually get the address of that object (a pointer) so that you can compare it to the this pointer.
The reference "operator" in the signature of the isitme method denotes a reference, that is, an alias for the object itself.
On the other hand, in the line if(this == &temp), the operator is used directly on the object and thus returns the address of the object (a pointer to it).
So, if you want to check if the entered reference is equal to this, you need to compare to a pointer, which is exactly what the referance operator returns.
& in the class parameter list means the object is passed by-reference. That is, temp is an alias for the class1 object. &temp is simply taking the address of that object and comparing it to the object pointed to by this. The two syntaxes are semantically different, you're not taking the address twice.

C++ interview about operator

Here is the code which basically implementing the = assignment for a class named CMyString, and the code is right.
CMyString& CMyString::operator =(const CMyString &str) {
if(this == &str)
return *this;
delete []m_pData;
m_pData = NULL;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);
return *this;
}
The instance is passed by reference, and the first 'if' is checking whether the instance passed in is itself or not. My question is: why does it use &str to compare, doesn't str already contain the address of the instance? Could any one explain how this line works?
Also, I just want to make sure that this contains the address of the object: Is this correct?
isn't str already contains the address of the instance
No. A reference is the object itself. It's not a pointer to the object.
(I. e., in the declaration of the function, &str stands for "reference to str" and not "address of str" - what you're talking about would be right if the function was declared like this:
CMyString& CMyString::operator =(const CMyString *str);
but it isn't.)
Address-of Operator and Reference Operator are different.
The & is used in C++ as a reference declarator in addition to being the address-of operator. The meanings are not identical.
int target;
int &rTarg = target; // rTarg is a reference to an integer.
// The reference is initialized to refer to target.
void f(int*& p); // p is a reference to a pointer
If you take the address of a reference, it returns the address of its target. Using the previous declarations, &rTarg is the same memory address as &target.
str passed by to the assignment operator is passed by reference, so it contains the actual object, not its address. A this is a pointer to the class a method is being called on, so if one wants to compare, whether passed object is the same object itself, he has to get the address of str in order to compare.
Note, that & behaves differently, depending on where it is used. If in statement, it means getting an address to the object it is applied to. On the other hand, if it is used in a declaration, it means, that the declared object is a reference.
Consider the following example:
int i = 42;
int & refToI = i; // A reference to i
refToI = 99;
std::cout << i; // Will print 99
int j = 42;
int * pJ = &j; // A pointer to j
*pJ = 99;
std::cout << j; // Will print 99
this is a pointer to the instance, so yes, it contains the address.
The whole point of verifying, if the passed object is this or not is to avoid unnecessary (or, possibly destructive) assignment to self.
While indeed a variable reference - denoted by the symbol & after the type name - underlying implementation is usually a pointer, the C++ standard seemingly does not specify it.
In its usage anyway, at the syntax level, a reference is used like a non referenced value of the same type, ie. more strictly speaking :
If the type of the variable is T &, then it shall be used as if it were of type T.
If you must write str.someMethod() and not str->someMethod() (without any overloading of the arrow operator), then you must use & to obtain the address of the value. In other words, a reference acts more or less like an alias of a variable, not like a pointer.
For more information about references and pointers, see these questions:
What's the meaning of * and & when applied to variable names?
What are the differences between a pointer variable and a reference variable in C++?
Why 'this' is a pointer and not a reference?

who can tell me "*this pointer" in details?

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;