8.8 — The hidden “this” pointer

One of the questions about classes that new object-oriented programmers often ask is, “When a member function is called, how does C++ keep track of which object it was called on?”. The answer is that C++ utilizes a hidden pointer named “this”! Let’s take a look at “this” in more detail.

The following is a simple class that holds an integer and provides a constructor and access functions. Note that no destructor is needed because C++ can clean up integer member variables for us.

Here’s a sample program that uses this class:

As you would expect, this program produces the result:


Somehow, when we call simple.setID(2);, C++ knows that function setID() should operate on object simple, and that m_id actually refers to simple.m_id. Let’s examine the mechanics behind how this works.

The hidden *this pointer

Take a look at the following line of code from the example above:

Although the call to function setID() looks like it only has one argument, it actually has two! When compiled, the compiler converts simple.setID(2); into the following:

Note that this is now just a standard function call, and the object simple (which was formerly an object prefix) is now passed by address as an argument to the function.

But that’s only half of the answer. Since the function call now has an added argument, the member function definition needs to be modified to accept (and use) this argument as a parameter. Consequently, the following member function:

is converted by the compiler into:

When the compiler compiles a normal member function, it implicitly adds a new parameter to the function named “this”. The this pointer is a hidden const pointer that holds the address of the object the member function was called on.

There’s just one more detail to take care of. Inside the member function, any class members (functions and variables) also need to be updated so they refer to the object the member function was called on. This is easily done by adding a “this->” prefix to each of them. Thus, in the body of function setID(),m_id (which is a class member variable) has been converted to this->m_id. Thus, when *this points to the address of simple, this->m_id will resolve to simple.m_id.

Putting it all together:
1) When we call simple.setID(2), the compiler actually calls setID(&simple, 2).
2) Inside setID(), the *this pointer holds the address of object simple.
3) Any member variables inside setID() are prefixed with “this->”. So when we say m_id = id, the compiler is actually executing this->m_id = id, which in this case updates simple.m_id to id.

The good news is that all of this happens transparently to you as a programmer, and it doesn’t really matter whether you remember how it works or not. All you need to remember is that all normal member functions have a *this pointer that refers to the object the function was called on.

*this always points to the object being operated on

New programmers are sometimes confused about how many *this pointers exist. Each member function has a *this pointer parameter that is set to the address of the object being operated on. Consider:

Note that the *this pointer alternately holds the address of object A or B depending on whether we’ve called a member function on object A or B.

Because *this is just a function parameter, it doesn’t add any memory usage to your class (just to the member function call, since that parameter goes on the stack while the function is executing).

Explicitly referencing *this

Most of the time, you never need to explicitly reference the “this” pointer. However, there are a few occasions where doing so can be useful:

First, if you have a constructor (or member function) that has a parameter with the same name as a member variable, you can disambiguate them by using “this”:

Note that our constructor is taking a parameter of the same name as a member variable. In this case, “data” refers to the parameter, and “this->data” refers to the member variable. Although this is acceptable coding practice, we find using the “m_” prefix on all member variable names provides a better solution by preventing duplicate names altogether!

Chaining member functions

Second, it can sometimes be useful to have a class member function return the object it was working with as a return value. The primary reason to do this is to allow a series of member functions to be “chained” together, so several member functions can be called on the same object! You’ve actually been doing this for a long time. Consider this common example where you’re outputting more than one bit of text using std::cout:

In this case, std::cout is an object, and operator<< is a member function that operates on that object. The compiler evaluates the above snippet like this:

First, operator<< uses std::cout and the string literal “Hello, ” to print “Hello, ” to the console. However, since this is part of an expression, operator<< also need to return a value (or void). If operator<< returned void, you’d end up with this:

which clearly doesn’t make any sense (and the compiler would throw an error). However, instead, operator<< returns *this, which in this context is just std::cout. That way, after the first operator<< has been evaluated, we get:

which then prints the user’s name.

In this way, we only need to specify the object (in this case, std::cout) once, and each function call passes it on to the next function to work with, allowing us to chain multiple commands together.

We can implement this kind of behavior ourselves. Consider the following class:

If you wanted to add 5, subtract 3, and multiply by 4, you’d have to do this:

However, if we make each function return *this, we can chain the calls together. Here is the new version of Calc with “chainable” functions:

Note that add(), sub() and mult() are now returning *this. Consequently, this allows us to do the following:

We have effectively condensed three lines into one expression! Let’s take a closer look at how this works.

First, calc.add(5) is called, which adds 5 to our m_value. add() then returns *this, which is a reference to calc. Our expression is now calc.sub(3).mult(4). calc.sub(3) subtracts 3 from m_value and returns calc. Our expression is now calc.mult(4). calc.mult(4) multiplies m_value by 4 and returns calc, which is then ignored. However, since each function modified calc as it was executed, calc’s m_value now contains the value ((0 + 5) - 3) * 4), which is 8.


The “this” pointer is a hidden parameter implicitly added to any member function. Most of the time, you will not need to access it directly, but you can if needed. It’s worth noting that “this” is a const pointer -- you can change the value of the underlying object it points to, but you can not make it point to something else!

By having functions that would otherwise return void return *this instead, you can make those functions chainable. This is most often used when overloading operators for your classes (something we’ll talk about more in chapter 9).

8.9 -- Class code and header files
8.7 -- Destructors

98 comments to 8.8 — The hidden “this” pointer

  • Matias

    With regards to the Simple (and *this remarks) of the first part of the tutorial:

    I’ve looked at the disassembly code to understand what actually goes on (reverse engineering ftw), specifically on the following line:

    This should be easier to examine since there’s no istream/cout bloat code. I’ll be referencing the following pictures:

    Picture A -> ASM code right before function call ->
    Picture B -> ASM code in Cheat Engine ->
    Picture C -> ASM code of function itself ->

    I guess it can be seen as "proof" as to what you’ve stated in the tutorial.

    Note: the compiler is automatically set to use the calling convention cdecl (unless i specify another convention, which we haven’t done).
    Here’s a link that explains calling conventions pretty well:
    Lets keep in mind that "Arguments are passed on the stack in Right-to-Left order" in the CDECL calling convention.

    (Picture A / B)
    Let’s start by examining the instructions on the function ASM code line by line:
    1) push 2 -> we’ve called setID() with an int argument of 2. (this is our rightmost argument)

    2) lea ecx, [simple] -> the brackets around "simple" work like the dereference operator * in c++ (after all, it is the "this" pointer we’re talking about). We’re assigning the value stored in this pointer (the simple object) into the ecx register, which we’ll use as an argument to our function. (our leftmost argument)

    3) call Simple::setID (0CF3355 - main.exe + 3355). Keep in mind we’ve only passed one argument into the function ourselves. But under the hood, there’s two things being passed: the address of the object we’re dealing with, and the value of the id we want to assign to that object. The function call, in ASM, effectively translates to:

    As Alex stated in the tutorial.

    Furthermore, if we look at the function code itself for setID() - Picture C:

    (will be corrected in a reply) ..

    So we can see through looking "under the hood" that the compiler does indeed treat:


    Hopefully this isn’t too confusing and it makes some sense. I posted this to sort of "reinforce" the concept of how the compiler actually goes about the task. I do admit that the way you explained it was easier for everyone to understand, but I thought I’d share this for people that want to see how it actually happens, sort of as being shown a mathematical proof to a concept 😛

    Anyways, enjoying the content as always. Keep it up!

    • Matias

      With respect to the function itself:

      - Preparing stack frame

      -> address of member m_iID is in the ecx register
      -> move the address of the member into the this pointer (dereferencing the pointer now leads to the int value)
      -> move the id argument we passed in into the ecx register
      -> move our value of id (in ecx) into the value of eax (the member variable) = this essentially is where the assignment happens

      - Exiting stack frame, return back to main

      Sorry for making this a bit confusing but ASM is a bit hard to explain in words 😛

      EDIT: Special note:

      on the assignment line, which is essentially:

      EAX here is indeed the pointer to a Simple object (its first element). Since our Simple class only has one member, this line is just simply how it is there, with no offset to the eax register.

      If we added a second member, say an int, the line to replace that second element would be:

      The [eax+0x4] is a dereference to the second member, and by moving ecx’s contents (the argument we passed in to setID()) we are effectively changing its value.

  • Ben

        setID(&simple, 2); // note that simple has been changed from an object prefix to a function argument!
    Note that this is now just a standard function call, and the object simple (which was formerly an object prefix) is now passed by address as an argument to the function.

    Don’t you mean "is now passed by reference"? Or is the ampersand intended to be used in the “address of” context here. Definitely can be confusing.

    Thanks for the great tutorial!

    • Alex

      It’s passed by address, and the ampersand in this context means “address-of”.

      Yes, it’s confusing, as the context of the ampersand varies depending on where it’s used. 🙁 I wish they’d used a different symbol.


    Isn’t it more appropriate to call it "Chaining Function Calls" rather than "Chaining Objects?" because that’s not what really happens.

    • Alex

      Well, it kind of does, as the object is chained from the output of one function into the input of another function. But I agree, calling it “Chaining Member Functions” is a clearer. Thanks for the feedback.

  • can you explain why did this code gave me "2" as output?

    using namespace std;
    class set
        int m_i;
            m_i = 0;
        set add(int i)
            m_i += i;
            return *this;
        int  getval()
            return m_i;
    int main()
        set s;

    • Tuan

      The method "add" didn’t return reference to set object, then output should be 2.

    • Alex

      Yes. Because add() is returning a set by value, which makes a copy. So when you call s.add(2), 2 is added to s, and then a copy of that s+2 is returned. So when the second .add(2) is executed, it’s executed on the copy, not the original.

      To fix this, add() should return set by reference, not by value.

  • Seth_the_coder

    Hi Alex,
    My name is Seth Mwebi from Kenya. I have been following your tutorials for over seven months now. Back then I knew nothing about programming but now I feel like am ready to go pro:). Thanks for the effort you put in maintaining this tutorial.


      Same here bro, Been following along with this tutorial since June. This has helped me so much. Right now, I’m in a course that requires a good knowledge of C++. I’ve tried many other online courses: Lynda, Udemy, and other online sources, but none of them felt right and they made me quit after like a day.However, due to this website, I am surviving through it. Thanks

  • sabbir hasan

    Calc &add(int value){m_value+=value;return *this;}

    IN THIS SEGMENT..why you use Calc &add.why you use class here?

    i’m not good at i can’t understand it.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter