Where is the 'this' pointer stored in computer memory?

C++This Pointer

C++ Problem Overview


Where exactly is the 'this' pointer stored in memory? Is it allocated on the stack, in the heap, or in the data segment?

#include <iostream>
using namespace std;

class ClassA
{
    int a, b;

    public:
        void add()
        {
            a = 10;
            b = 20;
            cout << a << b << endl;
        }
};

int main()
{
    ClassA obj;
    obj.add();
    return 0;
}

In the above code I am calling the member function add() and the receiver object is passed implicitly as the 'this' pointer. Where is this stored in memory?

C++ Solutions


Solution 1 - C++

The easiest way is to think of this as being a hidden extra argument that is always passed automatically.

So, a fictional method like:

size_t String::length(void) const
{
  return strlen(m_string);
}

is actually more like this under the hood:

size_t String__length(const String *this)
{
  return strlen(this->m_string);
}

and a call like:

{
  String example("hello");
  cout << example.length();
}

becomes something like:

cout << String__length(&example);

Note that the above transformation is simplified, hopefully to make my point a bit clearer. No need to fill up the comments with "whaaa, where's the marshalling for method overloading, huh?"-type objection, please. :)

That transforms the question into "where are arguments stored?", and the answer is of course "it depends". :)

It's often on the stack, but it could be in registers too, or any other mechanism that the compiler considers is good for the target architecture.

Solution 2 - C++

Other answers have done a very good job explaining how a typical compiler implements this (by passing it as an implicit first parameter to the function).

I think it's also useful to see what the C++ ISO spec explicitly says about this. According to the C++03 ISO spec, §9.3.2/1:

> In the body of a nonstatic (9.3) member function, the keyword this is a non-lvalue expression whose value is the address of the object for which the function is called.

It's important to note that this is not a variable - it's an expression, much in the same way that the expression 1 + 2 * 3 is an expression. The value of this expression is permitted to be stored pretty much anywhere. The compiler might put it on the stack and pass it as an implicit parameter to a function, or it might put it in a register, and it conceivably could put it in the heap or in the data segment. The C++ specification deliberately gives the implementation some flexibility here.

I think that the "language-lawyer" answer is "this is completely implementation-defined, and moreover this is technically not a pointer, but an expression that evaluates to a pointer."

Hope this helps!

Solution 3 - C++

this is usually passed as a hidden argument of the method (the only difference throughout different calling conventions is how).

If you call:

myClass.Method(1, 2, 3);

Compiler generates the following code:

Method(&myClass, 1, 2, 3);

Where the first parameter is actually the pointer to this.

Let's check the following code:

class MyClass
{
private:
    int a;

public:
    void __stdcall Method(int i)
    {
	    a = i;
    }
};

int main(int argc, char *argv[]) 
{
    MyClass myClass;
    myClass.Method(5);

    return 0;
}

By using __stdcall I forced the compiler to pass all parameters through the stack. If you then start the debugger and inspect the assembly code, you'll find something like the following:

     myClass.Method(5);
00AA31BE  push        5  
00AA31C0  lea         eax,[myClass]  
00AA31C3  push        eax  
00AA31C4  call        MyClass::Method (0AA1447h)  

As you see, the parameter of the method is passed through the stack, then address of myClass is loaded to eax register and again pushed on the stack. In other words, this is treated as a regular parameter of this method.

Solution 4 - C++

this is an rvalue (you cannot take its address), so it doesn't (necessarily) occupy memory at all. Depending on the compiler and the target architecture, it will often be in a register: i0 on a Sparc, ECX with MSVC on Intel, etc. When the optimizer is active, it can even move around. (I've seen it in different registers with MSVC).

Solution 5 - C++

this behaves mostly like a function argument, and as such will be stored on the stack or - if the binary calling conventions of the architecture allow that - in a register.

Solution 6 - C++

this isn't stored at a well-defined location! The object that it points to is stored somewhere, and has a well-defined address, but the address itself does not have a specific home address. It is communicated around in the program. Not only that, but there can be many copies of that pointer.

In the following imaginary init function, the object registers itself to receive events and timer callbacks (using imaginary event source objects). So after the registration, there are two additional copies of this:

void foo_listener::init()
{
   g_usb_events.register(this); // register to receive USB events
   g_timer.register(this, 5);   // register for a 5 second timer
}

I a function activation chain, there will also be multiple copies of the this pointer. Suppose we have an object obj and call its foo function. That function calls the same object's bar function, and bar calls another function called update. Each function activation level has the this pointer. It's stored in a machine register, or in a memory location in the stack frame of the function activation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnagaradderKanteshView Question on Stackoverflow
Solution 1 - C++unwindView Answer on Stackoverflow
Solution 2 - C++templatetypedefView Answer on Stackoverflow
Solution 3 - C++SpookView Answer on Stackoverflow
Solution 4 - C++James KanzeView Answer on Stackoverflow
Solution 5 - C++MvGView Answer on Stackoverflow
Solution 6 - C++KazView Answer on Stackoverflow