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 needs to be passed to the function and stored in memory).

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.

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

209 comments to 8.8 — The hidden “this” pointer

  • Tony Kolarek

    Yoo nascar. So I'm getting quite confused here.

    Why are we calling our setID function in the constructor? Is it just there to showing how "this" works?

    Why would we ever want to call the function 'setID()' inside the constructor, if we simply could do something like:

    Sorry for these dumb questions, and thanks yet again!

  • Gamer_to_be

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

    Suppose we have the following code. I know we can't make 'this' to point to something else. But I was curious to do that to see the error on line number 20 and 21. Why are the errors that different while their type are the same. Both are constant pointer to an object and both can't be assigned.

    One more Q:
    When myObject is created in the main, where m_x and m_y are allocated memory? in the Stack space belongs to the main where 'zebra' is defined? or in the global space?

    • nascardriver

      `this` is a `const` pointer while `test2` is a non-`const` pointer to a `const` object.

      `myObject` and all of its members are allocated on the stack.

  • SaMIRa

    I know I made the code below unnecessarily complicated. I was trying to play around with pointers, references and constants.
    I got the same correct answer but my code got compile-time warnings while your code doesn't give any of those warnings. As far as I have learned from this section, 'this' is a const pointer pointing to the current object passed implicitly by compiler to the all normal member functions as function parameter. My question is why your code which returns the object as function parameter doesn't give any warning regarding 'returning address of local variable or temporary' but my code got three warnings for each return part of 'add', 'sub', and 'mult' member function. I think we both return local variables in the form of function arguments.

    "returning address of local variable or temporary"
    "returning address of local variable or temporary"
    "returning address of local variable or temporary"

    Thank you.

    • nascardriver

      `this` is only `const` if the function is `const`. Otherwise it's non-`const`.

      You're returning references to a pointer. The `this`-pointer is a local variable.

    • Ngoc_Hai

      im not good English!
      Calc* const add()
      {
      ...
      return this;
      }

      because this actually is Calc* const this
      I don't understand what you mean when you write Calc* const &,
      Can you explain your understanding?
      What the '&' operator means?
      thank you so much!

      • Karl Phazer

        Nascardriver, please confirm this but as I understand it:
        Calc* const& is a reference to a constant pointer to a Calc object.

        Note that:
        a) You can assign a <non-const integer> to a <pointer to const integer>.
            Although you can change the value directly, you can't change it via the pointer.

        b) References are always constant.
            You can't change the variable they point to after initialization.
            You can change the value they point except if they are prefixed with const.

        • Karl Phazer

          Argh!

          I was so caught up with the formatting and 'symmetricality' of the code that I didn't even bother to really check it works and added the line where I supposedly change the address of an initialized reference..  Even if I stated in the end that this can't be done.

          I was so proud of how neat it looked :( could you edit out lines 20 & 15 from the code segment?

        • nascardriver

          You already confirmed yourself that you're right, which is a great way of learning.

          • Karl Phazer

            Well yes, I was just feeling like stepping on your territory since I was answering to another person and thus wanted to be sure I wasn't giving away false information. Sorry once more for posting so much questions lately. I'll start using Stack Exchange from now on, more people there to read my confused babblings :)

            Also I really want to tell you and Alex that you've done totally awesome work with this site. I've preferred video tutorials for years (and gone through a lot of frustration while doing so) but it feels great to read stuff when there's good stuff to be read. This has led to the revelation that there are lots of books that contain information which simply isn't available in other formats.

            Respect.

  • reference to a pointer this

    Oh! My mind has been BLOWWWWWWWWWWN away by this chaining example!!! OMG! These wonderful things can only be done in C++ NOT any language!! Imagine lame Python:))
    Thank you Alex and Nascadriver! I have always wanted to know how "std::cout along with a lot of << operators" is implemented!

    I think we could even  write something like this too:

    By the way, I have a couple of question:

    1) is the following as efficient as yours?

    2) >>Why can't we use 'this->' when we want to use member value initialization list?

    • nascardriver

      1) Yes. But now the caller has to worry about you returning a `nullptr`. If `nullptr` isn't a valid value, use references.

      2) It would be redundant. You can only initialize members of the current class anyway.

      • test

        2) It would be redundant. You can only initialize members of the current class anyway.

        I meant, it is not working , I got compile-time error when use 'this' in member value initialization list.

  • Rose

    [[Note that no destructor is needed because C++ can clean up integer member variables for us.]]

    If we had the following, would we need a destructor?

    [[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.]]
    what kind of member functions aren't normal and don't those have 'this' as an implicit parameter?

    [[since that parameter goes on the stack while the function is executing]]
    'is executing' or 'finishes executing'?

    • nascardriver

      You're leaking the entire object, no cleanup is happening at all. This isn't something a destructor in `Simple` could prevent.

      `static` member functions don't have a `this` pointer, because they're independent of instances.

      "is executing"

Leave a Comment

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