Search

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:

2

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 automatically, 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!

Some developers prefer to explicitly add this-> to all class members. We recommend that you avoid doing so, as it tends to make your code less readable for little benefit. Using the m_ prefix is a more readable way to differentiate member variables from non-member (local) variables.

Recommendation: Do not add this-> to all uses of your class members. Only do so when you have a specific reason to.

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 needs 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). Instead, operator<< returns *this, which in this context is the std::cout object. 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 just a reference to calc, so calc will be the object used in the subsequent evaluation. Next calc.sub(3) evaluates, which subtracts 3 from m_value and again returns calc. Finally, calc.mult(4) multiplies m_value by 4 and returns calc, which isn’t used further, and is thus ignored.

Since each function modified calc as it was executed, calc’s m_value now contains the value (((0 + 5) - 3) * 4), which is 8.

Summary

The “this” pointer is a hidden parameter implicitly added to any non-static 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
Index
8.7 -- Destructors

155 comments to 8.8 — The hidden “this” pointer

  • Yaroslav

    I have a small war of concepts in my head.
    we have internal c++ classes like int and when we deference pointer to an int object it will deference to an object value not to an object itself.
    and we have 'this', if we deference this it will become an object.
    do i understand correctly that when we deference pointer to internal classes like int it will first deference it to an object/variable and then invisibly dissolve that object to a value that it holds and will give us it?

    • Indirection of a pointer to an object yields a reference to the pointed-to object. It doesn't matter what that object is. Objects have values, but there's no such thing as dissolving to a value.
      `int` is not a class-type, it's a fundamental type.

  • Alireza

    Hello and thanks for "this",
    This is very useful.(I've seen "this" in many GUI applications.)
    1. You said that the compiler would evaluate the following code into the second one:

    into:

    So why can't I use the second one in codes, causes errors!

    2. Is here necessary to use "this" pointer ?

    3. What does "*this" actually mean and refer to ?
    And why can't we use "this" alone ?

    4. I forgot that XD (doesn't matter)

    Thanks

    • 1.
      There is nothing called "func" available in the caller's scope.
      You're using the regular function-call syntax, but the "this" argument is automatically, not by the programmer.
      You only have to pass the this-pointer yourself if you're using function pointers, eg.

      2.
      If you intention is to get the type info of the this-pointer, yes.

      3.
      > What does "*this" actually mean and refer to
      `this` is a pointer to the object that the function was called on.
      `*this` is a reference to the object that the function was called on.

      > why can't we use "this" alone
      `add` was declared to return a reference. `this` is a pointer. Dereferencing `this` gives you a reference.

  • Napalm

    I'm a little confused by the * after Simple. Usually the * is not against the type name, but I think I'm misunderstanding it's meaning here.

    I looked back at the chapters on pointers but couldn't see the same syntax.

    • It means that `this` is a pointer. Have another look at lesson 6.7, and maybe the lessons after that. This is essential.
      The `const` in that place means that the pointer is constant, but not the value it's pointing to.

  • Nguyen

    Hi

    Please let me know if they are the same.

    Thanks,

  • TTT

    Hi,
    Could you tell me why the output of my code is 3 3 1 3? I was expecting 1 3 3 3. Thanks!

    • The order of execution of function arguments is undefined. If you need a specific order, store the results in variables and print those.

      • TTT

        Thank you! I also find this https://en.cppreference.com/w/cpp/language/eval_order.
        Now I get it. The order of evaluation of the operands of almost all C++ operators is unspecified.

  • Barne

    Gotta admit this is the first time you completely lost me, Alex. I know the syntax and what it does but I do not understand how.
    You had me through the std::cout and "<<" operator returning void part. This makes sense since the + operator just returns the sum of its parts (I think?).

    Although I have no idea why you make the function return a reference (Calc&) or what the "." operator really returns by default (just void?).

    My current "theory" or grasp of the situation is that "this" contains the memory adress to the class it's currently in, and returning a pointer makes it dereference it via the reference? Although I dont understand the part with "calc.mult(4). calc.mult(4)" or "calc.sub(3).mult(4). calc.sub(3)" at all.

    Shouldn't it just be calc.sub(3).mult(4) after add returns Calc?

    Regardless if I'm right, I think this chapter could benefit from a little bit more thorough explanation between the steps. The jump from std::cout section to the Calc explanation was a bit too large imo.

    • Hi Barne!

      > You had me through the std::cout and "<<" operator returning void part
      "However, instead, operator<< returns *this, which in this context is just std::cout."

      > + operator just returns the sum of its parts
      It can do anything, eg. @std::string appends 2 strings. For arithmetic types, it usually returns the sum of its operands.

      > I have no idea why you make the function return a reference
      Let's say it returned a copy

      calc.add(5) would increase @calc.m_value and return a copy. @sub is then called on the copy, it doesn't affect @calc(3). Same for @mult(4).
      The program would print 5, since the only operation performed on @calc was @calc.add(5).
      By returning a reference, all operations are performed on @calc.

      > what the "." operator really returns by default
      It lets you access the object's members. I'm not sure if this could be described as a return type.

      > "this" contains the memory adress to the class it's currently in
      Correct.

      > returning a pointer makes it dereference it via the reference?
      We're not returning a pointer, we're dereferencing @this, which gives us a reference to the object @this is pointing to. This reference is then returned.

      > Although I dont understand the part with "calc.mult(4). calc.mult(4)" or "calc.sub(3).mult(4). calc.sub(3)" at all.
      Some of those dots are periods to end the sentence. @Alex, this needs an update.
      Here's the same text with the sentences terminated by semicolons.
      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;

      • Alex

        Noted, the sentences in question have been rewritten so they don't end with an ambiguous period.

      • Barne

        Aha, I think this makes it much clearer.

        Since we are just returning *this, the first function call is just evaluated like a regular function call, which then tells us which class to use the "." operator on next.

        So if we wanted to, we could do something like this:
        Calc.add(5).SelectClass(MysteryClass).WierdFunctionFromMysteryClass(6)

        i.e: We could return memory adresses to completely other classes using other pointers than "*this". So in the example above, the function "SelectClass" might return the adress of a completely other class, which would then allow us to call its functions (here represented by the "WierdFunction".

        It's unlikely that what I just wrote is something you would actually do, but it's possible? At least the idea is that the since the function just returns a dereferenced memory adress, in a sense it just "replaces" the function with the name of the class after performing its code.

        Would the thing I wrote be possible to do or does the syntax prevent us from chaining functions from other classes? If so, could I use private variables from "Calc" when calling "WeirdFunction"?

        Even if my last batch of code and questions are completely wrong I think I get the regular "*this" pointer usage at least. Thanks Nascar!

        • Chaining functions doesn't give them any more access than calling them step by step.
          @WierdFunctionFromMysteryClass knows it was called on whatever @SelectClass returned, but it doesn't know about anything before that. Even if it did, it could only access private members if it has been declared a friend of that class.

          > It's unlikely that what I just wrote is something you would actually do
          This is common for member access.

  • Louis Cloete

    In the first sentence of the paragraph directly above "“this” always points to the object being operated on," you again use "transparently" where I think you should use "opaquely" or "hidden away from you as programmer."

  • Rashid

    int main()
    {
        Simple A(1); // *this = &A inside the Simple constructor
        Simple B(2); // *this = &B inside the Simple constructor
        A.setID(3); // *this = &A inside member function setID
        B.setID(4); // *this = &B inside member function setID

        return 0;
    }

    I am not sure how is *this = &A
    Because *this should contain actual object A by my understanding, I don't get why the value of this pointer contains an address. In my current understanding, I would say that this = &A. Can you please explain why I am wrong?

    • Rashid

      Hi Alex,
      I am not sure how is *this = &A
      Because *this should contain actual object A by my understanding, I don't get why the value of this pointer contains an address. In my current understanding, I would say that this = &A. Can you please explain why I am wrong?

    • Alex

      I agree, I'll update the lesson to remove the asterisk before "this".

  • Rahul Kumar

    Hi Alex, although I understood the logic here but seeing the term <Calc&> for the first time. Can you please explain this.

    • It's a reference. Lesson 6.11, 7.4a

      • Rahul Kumar

        But <&> keyword is used before the variable name in "reference" and not after it!

        • @Calc is not a variable, it's a type.

        • Arno Adam

          I'm not quite sure about this myself...
          As far as I understand it, "Calc&" is what defines what kind of datatype the function will return. In the unaltered example above it, the function just changed m_value and didn't return anything, so it was of type "void". In the example below, its intention is to return a pointer, correct? So why isn't it "Calc*" instead of "Calc&"?

          EDIT: I just read the sentence below that, where it says "[...]then returns *this, which is a reference to calc". So it's actually a reference instead of a pointer? I know they are pretty similar, but this implies that underneath the surface, they are handled exactly the same...

          • & applied to the right side of a type is a reference.
            & applied to the left side of a variable is a pointer.
            * applied to the right side of a type is a pointer.
            * applied to the left side of a pointer is a reference.

            Under the surface, pointers and references are the same.

  • Lan

    hi Alex

    the fraction don't reduce when i  enter 6 to m_numerator and 12 to m_denominator

  • vitrag shah

    hey,
    first of all sorry, because I am not asking the doubt about this chapter

    I am doing a complex maths operation in that there I got an error :(
    error: expression cannot be used as a function

    I just want to know what that what this error mean?

  • Winston Lai

    Hi,

    I was wondering why to you return by reference for the member function. It is in consistent with the return type since we are returning *this, which is a pointer that points to the address of the object. I am confused, can you please clarify?

    • > *this, which is a pointer that points to the address of the object
      "*this" isn't the pointer, "this" is the pointer. It doesn't point to an address, it points to the object.
      "*this" gives us the object that "this" is pointing to.

      • Winston Lai

        Hi nascardriver, so wouldn't "this" be a object that is passed back to the caller by value? Also, if this is return by reference, since "this" pointer is a local pointer,  if we are dereferencing "this" to the get actual object before the function ends, then return as a reference, wouldn't the reference be gone since "this" is destroy be the end ot eh function? Thanks for your reply!!

        • > wouldn't "this" be a object
          > since "this" pointer is a local pointer
          You can't have both. @this is a pointer.

          > if we are dereferencing "this" to the get actual object before the function ends, then return as a reference, wouldn't the reference be gone
          No, @this points to the object the function is called on

  • Ishak

    Does std::cout return as *this or as *this-> ???

    • @std::cout doesn't return anything, it's an object, not a function.

      @std::cout.operator<< returns a reference to *this.

      References
      std::ostream::operator<< - http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/

  • Hi Alex!
    I see "The “this” pointer is a hidden parameter implicitly added to any member function" but I can't use "this" in static member function.
    Thank you!

    • nascardriver

      The nullPointer!

      The this-pointer points to the instance on which the function is called. Since static functions don't have an instance they're called on, there's no this-pointer.
      I understand your confusion, Alex' sentence might be better written as
      "The “this” pointer is a hidden parameter implicitly added to any non-static member function".

  • Laksh Singla

    Hi Alex, I had a few doubts wrt above piece of code. This does not work as expected, i.e calls chain and the first print value shows 0 + 19 - 7. But c only gets updated as per the first call i.e value of c.x after the first statement in main remains just 19. The only logical explanation that I was able to think of that returning *this created a new object and returned it on which subtract(7) ran and then a new object was again returned which printed 12. Therefore after the first statement, value remained just 19. Please could you explain this and correct me if I am wrong.
    Thank you

    • nascardriver

      Hi Laksh!

      You're returning by copying. See lesson 6.11, 6.11a, 7.3 and 7.4a, especially 7.4a.

  • Jagadeesh Takkalaki

    Alex, I have got confused with object creation with pointer.
    Below code Snippet supose to give error, But I am getting output as hello world.How actually it will work internally??
    Class A
    {
    public:
        void foo()
       {
         cout<<"Hello World\n";
       }

    };

    int main()
    {
    A *a=NULL;
    a->foo(); //Here I geeting output Hello world
    return 0;
    }

    • nascardriver

      Hi Jagadeesh!

      @foo is the same for every @A you instantiate so there will be only one @foo function for all objects. When you call @foo, @a will be passed to @foo (Your compiler adds a 'this' parameter to all member functions). Since @foo doesn't use the 'this' parameter there is no problem with calling @foo on a nullptr. If @foo were to access a run-time member of @A you'd get a crash.

      Please use code tags, uniform initialization, and nullptr.

  • Micah

    Right before the summary:
    "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."

    You're missing just one parenthesis in:
    ((0 + 5) - 3) * 4)

    Should be:
    (((0 + 5) - 3) * 4)

    Almost meaningless correction but I'll bet it'll bother you now that you know it's there :)

  • Dekasi

    Regarding this example:

    can we do something like this:

    It keeps saying that an identifier is expected.

  • Steve

    I remember encountering something like

    Does that has anything to do with the hidden this pointer?

    • Alex

      Yes, assuming you call this from within a member function, this would dynamically allocate a copy of the implicit object (via the copy constructor)

  • 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 -> https://media.discordapp.net/attachments/364055119190556674/401153899307859970/image.png
    Picture B -> ASM code in Cheat Engine -> https://media.discordapp.net/attachments/364055119190556674/401154651082194944/image.png
    Picture C -> ASM code of function itself -> https://media.discordapp.net/attachments/364055119190556674/401156211661209610/image.png?width=400&height=166

    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: https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions#CDECL.
    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:

    as

    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 :P

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

    • Matias

      With respect to the function itself:
      https://media.discordapp.net/attachments/364055119190556674/401156211661209610/image.png

      - 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 :P

      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

    Quote:
        
        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.

  • DOG_TRAINER

    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?

    #include<iostream>
    using namespace std;
    class set
    {
        int m_i;
    public:
        set()
        {
            m_i = 0;
        }
        set add(int i)
        {
            m_i += i;
            return *this;
        }
        int  getval()
        {
            return m_i;
        }
    };
    int main()
    {
        set s;
        s.add(2).add(2);
        cout<<s.getval();
    }

    • Tuan

      Hi,
      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.

    • DOG_TRAINER

      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 pointer.so i can't understand it.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]