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

Summary

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
Index
8.7 -- Destructors

96 comments to 8.8 — The hidden “this” pointer

  • 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 C++ code inside [code][/code] tags to use the syntax highlighter