How to Use the this Pointer in C++
In this tutorial, we will first understand the concept of the this
pointer.
Then, we will demonstrate its uses with the help of examples. Lastly, we will see how this
differs from *this
.
Use the this
Pointer in C++
The this
pointer is simply an implicitly available pointer that, in a non-static class member function scope, refers or points to the calling object. If you didn’t get it by definition, let’s look at some fundamentals to understand the concept.
We know that all the non-static data members have a separate copy for each object. However, the member functions code is shared among all the objects.
All the objects of the same class access the same function definition from the code segment when they need to invoke it. The compiler needs to know the calling object (who is currently calling a member function) information to access or update the right data member specific to this particular calling object.
So, given that the function definitions are the same, how does the compiler get the calling object information?
The simple answer is that during the compilation of the program, the compiler automatically adds a hidden implicit pointer parameter in the member functions. This implicit pointer is known to be as this
pointer.
Whenever a member function gets invoked through a particular class object, the calling object is automatically supplied as a hidden argument to this
pointer. Now, the compiler can use this pointer to access or modify the right data member specific to the calling object.
this
pointer is not required with the static members of the class as these members (functions and data members) are shared among all objects.The update or access to the static members is not specific to any object. We can even access these members without creating an object of the class.
Therefore, the compiler does not use the this
operator with these members.
Let’s look into the code example to understand why we are saying that the compiler implicitly uses this
pointer and when it is handy.
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string Name;
public:
Person(string Name) {
this->Name = Name; // this->Name is the private member for this object
}
void PrintName() { cout << this->Name << endl; }
void PrintName1() { cout << Name << endl; }
};
int main() {
Person P("Alexa");
P.PrintName();
P.PrintName1();
return 0;
}
The above code example defines a Person
class with two different member functions to print the private data member Name
. The first statement in the main()
function generates a Person
object and passes Alexa
as an argument to the constructor.
Now, this->Name
in the constructor helps the compiler distinguish between local parameter Name
and private data member Name
.
The subsequent code of main()
calls printName()
and printName1()
through P (i.e., P becomes the caller object).
Output:
Alexa
Alexa
The output of both the functions is the same. This is because the compiler implicitly precedes this->
with Name
in the PrintName1()
.
Difference Between this
and *this
in C++
So far, we are clear with the concept that this
is a pointer to an object. For an obj
of type Person
, this
is of type Person*
.
Another thing to remember is that the this
pointer is always an rvalue
, which can not be modified. However, *this
de-references the this
pointer.
After going through a sufficient background, let’s look at an example code to understand the difference between this
and *this
.
#include <iostream>
using namespace std;
class Counter {
private:
int Count;
public:
Counter() { this->Count = 0; }
void IncreaseCount() { Count++; }
void PrintCount() { cout << this->Count << endl; }
Counter* GetCount_Pointer() { return this; }
Counter GetCount_Copy() { return *this; }
Counter& GetCount_Reference() { return *this; }
};
int main() {
// Section-A
cout << "Sectio-A" << endl;
Counter C1;
C1.IncreaseCount();
Counter* CounterPtr =
C1.GetCount_Pointer(); // CounterObj will be pointing to C1
CounterPtr->IncreaseCount();
C1.PrintCount();
// Section-B
cout << "Section-B" << endl;
Counter C2;
C2 = C1.GetCount_Copy();
C1.IncreaseCount();
C1.PrintCount();
C2.PrintCount();
// Section-C
cout << "Section-B" << endl;
Counter& CounterRef = C1.GetCount_Reference();
CounterRef.PrintCount();
return 0;
}
This code snippet creates a Counter
class with multiple methods to GetCount
methods. The first method (i.e., GetCount_Pointer
) returns the value of this
pointer which is simply an address of the calling object.
The GetCount_Copy
method returns *this
while the return type is a Counter
type object. So, this function will return a deep copy of the calling object which means modifying the returned copy will not affect the original copy.
The last GetCount_Reference
method also returns *this
, but the return type of this method is a reference object (i.e., Counter&
). Instead of creating a new deep copy, the compiler will return an alias or reference to the original object.
Any changes made through the alias will also be reflected in the original object.
Before discussing the main driver code, let’s look at the program’s output.
Output:
Sectio-A
2
Section-B
3
2
Section-B
3
Section-A of the main
method first declares the C1
object of Counter
type and increments its Count
through IncreaseCount()
. Later, it initializes a CounterPtr
pointer with the address returned by C1.GetCount_Pointer()
.
Now, the CounterPtr
will be pointing to C1
. Therefore, calling the increment function through CounterPtr
also modifies the C1
.
C2 = C1.GetCount_Copy()
in section-B deeply copies all the current contents of C1
to C2
as C1.GetCount_Copy()
is replaced with a copy of C1
. Therefore, increasing count for C1
is not effecting C2
.
The section-C declares a reference variable to Counter
type and initializes it with whatever is being returned by C1.GetCount_Reference()
. As C1.GetCount_Reference()
returns an alias of C1
, therefore, CounterRef
becomes another name for C1
.
The statement Counter& CounterRef = C1.GetCount_Reference();
becomes logically equivalent to Counter& CounterRef = C1
.
Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.
LinkedIn