Is the “this” pointer just a compile time thing?











up vote
28
down vote

favorite
3












I asked myself whether the this pointer could be overused since I usually use it every single time I refer to a member variable or function. I wondered if it could have performance impact since there must be a pointer which needs to be dereferenced every time. So I wrote some test code



struct A {
int x;

A(int X) {
x = X; /* And a second time with this->x = X; */
}
};

int main() {
A a(8);

return 0;
}


and surprisingly even with -O0 they output the exact same assembler code.



Also if I use a member function and call it in another member function it shows the same behavior. So is the this pointer just a compile time thing and not an actual pointer? Or are there cases where this is actually translated and dereferenced? I use GCC 4.4.3 btw.










share|improve this question




















  • 6




    Possible duplicate of Is there overhead using this-> in c++?
    – underscore_d
    yesterday










  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Samuel Liew
    8 hours ago















up vote
28
down vote

favorite
3












I asked myself whether the this pointer could be overused since I usually use it every single time I refer to a member variable or function. I wondered if it could have performance impact since there must be a pointer which needs to be dereferenced every time. So I wrote some test code



struct A {
int x;

A(int X) {
x = X; /* And a second time with this->x = X; */
}
};

int main() {
A a(8);

return 0;
}


and surprisingly even with -O0 they output the exact same assembler code.



Also if I use a member function and call it in another member function it shows the same behavior. So is the this pointer just a compile time thing and not an actual pointer? Or are there cases where this is actually translated and dereferenced? I use GCC 4.4.3 btw.










share|improve this question




















  • 6




    Possible duplicate of Is there overhead using this-> in c++?
    – underscore_d
    yesterday










  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Samuel Liew
    8 hours ago













up vote
28
down vote

favorite
3









up vote
28
down vote

favorite
3






3





I asked myself whether the this pointer could be overused since I usually use it every single time I refer to a member variable or function. I wondered if it could have performance impact since there must be a pointer which needs to be dereferenced every time. So I wrote some test code



struct A {
int x;

A(int X) {
x = X; /* And a second time with this->x = X; */
}
};

int main() {
A a(8);

return 0;
}


and surprisingly even with -O0 they output the exact same assembler code.



Also if I use a member function and call it in another member function it shows the same behavior. So is the this pointer just a compile time thing and not an actual pointer? Or are there cases where this is actually translated and dereferenced? I use GCC 4.4.3 btw.










share|improve this question















I asked myself whether the this pointer could be overused since I usually use it every single time I refer to a member variable or function. I wondered if it could have performance impact since there must be a pointer which needs to be dereferenced every time. So I wrote some test code



struct A {
int x;

A(int X) {
x = X; /* And a second time with this->x = X; */
}
};

int main() {
A a(8);

return 0;
}


and surprisingly even with -O0 they output the exact same assembler code.



Also if I use a member function and call it in another member function it shows the same behavior. So is the this pointer just a compile time thing and not an actual pointer? Or are there cases where this is actually translated and dereferenced? I use GCC 4.4.3 btw.







c++ gcc this this-pointer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









sds

38k1492164




38k1492164










asked 2 days ago









Yastanub

390212




390212








  • 6




    Possible duplicate of Is there overhead using this-> in c++?
    – underscore_d
    yesterday










  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Samuel Liew
    8 hours ago














  • 6




    Possible duplicate of Is there overhead using this-> in c++?
    – underscore_d
    yesterday










  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Samuel Liew
    8 hours ago








6




6




Possible duplicate of Is there overhead using this-> in c++?
– underscore_d
yesterday




Possible duplicate of Is there overhead using this-> in c++?
– underscore_d
yesterday












Comments are not for extended discussion; this conversation has been moved to chat.
– Samuel Liew
8 hours ago




Comments are not for extended discussion; this conversation has been moved to chat.
– Samuel Liew
8 hours ago












11 Answers
11






active

oldest

votes

















up vote
64
down vote



accepted











So is the this pointer just a compile time thing and not an actual pointer?




It very much is a run time thing. It refers to the object on which the member function is invoked, naturally that object can exist at run time.



What is a compile time thing is how name lookup works. When a compiler encounters x = X it must figure out what is this x that is being assigned. So it looks it up, and finds the member variable. Since this->x and x refer to the same thing, naturally you get the same assembly output.






share|improve this answer





















  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Samuel Liew
    8 hours ago


















up vote
23
down vote













It is an actual pointer, as the standard specifies it (§12.2.2.1):




In the body of a non-static (12.2.1) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.




this is actually implicit every time you reference a non-static member variable or member function within a class own code. It is also needed (either when implicit or explicit) because the compiler needs to tie back the function or the variable to an actual object at runtime.



Using it explicitly is rarely useful, unless you need, for example, to disambiguate between a parameter and a member variable within a member function. Otherwise, without it the compiler will shadow the member variable with the parameter (See it live on Coliru).






share|improve this answer



















  • 6




    You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
    – Toby Speight
    yesterday










  • It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
    – Martin Bonner
    yesterday






  • 2




    "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
    – Tezra
    yesterday


















up vote
14
down vote













this always has to exist when you are in a non-static method. Whether you explicitly use it or not, you have to have a reference to the current instance, and this is what this gives you.



In both cases, you are going to access memory through the this pointer. It's just that you can omit it in some cases.






share|improve this answer























  • Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
    – Draco18s
    2 days ago


















up vote
13
down vote













This is almost a duplicate of How do objects work in x86 at the assembly level?, where I comment the asm output of some examples, including showing which register the this pointer was passed in.





In asm, this works exactly like a hidden first arg, so both the member-function foo::add(int) and the non-member add which takes an explicit foo* first arg compile to exactly the same asm.



struct foo {
int m;
void add(int a); // not inline so we get a stand-alone definition emitted
};

void foo::add(int a) {
this->m += a;
}

void add(foo *obj, int a) {
obj->m += a;
}


On the Godbolt compiler explorer, compiling for x86-64 with the System V ABI (first arg in RDI, second in RSI), we get:



# gcc8.2 -O3
foo::add(int):
add DWORD PTR [rdi], esi # memory-destination add
ret
add(foo*, int):
add DWORD PTR [rdi], esi
ret





I use GCC 4.4.3




That was released in January 2010, so it's missing nearly a decade of improvements to the optimizer, and to error messages. The gcc7 series has been out and stable for a while. Expect missed optimizations with such an old compiler, especially for modern instruction sets like AVX.






share|improve this answer




























    up vote
    9
    down vote













    After compilation, every symbol is just an address, so it can't be a run-time issue.



    Any member symbol is compiled to an offset in the current class anyway, even if you didn't use this.



    When name is used in C++ it can be one of the following.




    • In the global namespace (like ::name), or in the current namespace, or in the used namespace (when using namespace ... been used)

    • In the current class

    • Local definition, in upper block

    • Local definition, in current block


    Therefore, when you write code, the compiler should scan each, in a manner to look for the symbol name, from the current block and up to the global namespace.



    Using this->name helps the compiler to narrow the search for name to only look for it in the current class scope, meaning it skips local definitions, and if not found in class scope, do not look for it in the global scope.






    share|improve this answer






























      up vote
      5
      down vote













      Here is a simple example how "this" could be useful during runtime:



      #include <vector>
      #include <string>
      #include <iostream>

      class A;
      typedef std::vector<A*> News;
      class A
      {
      public:
      A(const char* n): name(n){}
      std::string name;
      void subscribe(News& n)
      {
      n.push_back(this);
      }
      };

      int main()
      {
      A a1("Alex"), a2("Bob"), a3("Chris");
      News news;

      a1.subscribe(news);
      a3.subscribe(news);

      std::cout << "Subscriber:";
      for(auto& a: news)
      {
      std::cout << " " << a->name;
      }
      return 0;
      }





      share|improve this answer




























        up vote
        3
        down vote














        since I usually use it every single time I refer to a member variable or function.




        You always use this when you refer to a member variable or function. There is simply no other way to reach members. The only choice is implicit vs explicit notation.



        Let's go back to see how it was done before this to understand what this is.



        Without OOP:



        struct A {
        int x;
        };

        void foo(A* that) {
        bar(that->x)
        }


        With OOP but writing this explicitly



        struct A {
        int x;

        void foo(void) {
        bar(this->x)
        }
        };


        using shorter notation:



        struct A {
        int x;

        void foo(void) {
        bar(x)
        }
        };


        But the difference is only in source code. All are compiled to same thing. If you create a member method, the compiler will create a pointer argument for you and name it "this". If you omit this-> when referring to a member, the compiler is clever just enough to insert it for you most of the time. That's it. The only difference is 6 less letters in the source.



        Writing this explicitly makes sense when there is an ambiguity, namely another variable named just like your member variable:



        struct A {
        int x;

        A(int x) {
        this->x = x
        }
        };


        There are some instances, like __thiscall, where OO and non-OO code may end bit different in asm, but whenever the pointer is passed on stack and then optimized to a register or in ECX from the very beginning doesn't make it "not a pointer".






        share|improve this answer




























          up vote
          2
          down vote













          Your machine does not know anything about class methods, they are normal functions under the hood.
          Hence methods have to be implemented by always passing a pointer to the current object, it's just implicit in C++, i.e. T Class::method(...) is just syntactic sugar for T Class_Method(Class* this, ...).



          Other languages like Python or Lua choose to make it explicit and modern object-oriented C APIs like Vulkan (unlike OpenGL) use a similar pattern.






          share|improve this answer




























            up vote
            2
            down vote













            "this" can also safeguard against shadowing by a function parameter, for example:



            class Vector {
            public:
            double x,y,z;
            void SetLocation(double x, double y, double z);
            };

            void Vector::SetLocation(double x, double y, double z) {
            this->x = x; //Passed parameter assigned to member variable
            this->y = y;
            this->z = z;
            }


            (Obviously, writing such code is discouraged.)






            share|improve this answer

















            • 1




              Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
              – Tezra
              yesterday












            • Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
              – Trass3r
              16 hours ago


















            up vote
            2
            down vote













            if the compiler inlines a member function that is called with static rather than dynamic binding, it might be able to optimize away the this pointer. Take this simple example:



            #include <iostream>

            using std::cout;
            using std::endl;

            class example {
            public:
            int foo() const { return x; }
            int foo(const int i) { return (x = i); }

            private:
            int x;
            };

            int main(void)
            {
            example e;
            e.foo(10);
            cout << e.foo() << endl;
            }


            GCC 7.3.0 with the -march=x86-64 -O -S flag is able to compile cout << e.foo() to three instructions:



            movl    $10, %esi
            leaq _ZSt4cout(%rip), %rdi
            call _ZNSolsEi@PLT


            This is a call to std::ostream::operator<<. Remember that cout << e.foo(); is syntactic sugar for std::ostream::operator<< (cout, e.foo());. And operator<<(int) could be written two ways: static operator<< (ostream&, int), as a non-member function, where the operand on the left is an explicit parameter, or operator<<(int), as a member function, where it’s implicitly this.



            The compiler was able to deduce that e.foo() will always be the constant 10. Since the 64-bit x86 calling convention is to pass function arguments in registers, that compiles down to the single movl instruction, which sets the second function parameter to 10. The leaq instruction sets the first argument (which might be an explicit ostream& or the implicit this) to &cout. Then the program makes a call to the function.



            In more complex cases, though—such as if you have a function taking an example& as a parameter—the compiler needs to look up this, as this is what tells the program which instance it’s working with, and therefore, which instance’s x data member to look up.



            Consider this example:



            class example {
            public:
            int foo() const { return x; }
            int foo(const int i) { return (x = i); }

            private:
            int x;
            };

            int bar( const example& e )
            {
            return e.foo();
            }


            The function bar() gets compiled to a bit of boilerplate and the instruction:



            movl    (%rdi), %eax
            ret


            You remember from the previous example that %rdi on x86-64 is the first function argument, the implicit this pointer for the call to e.foo(). Putting it in parentheses, (%rdi), means look up the variable at that location. (Since the only data in an example instance is x, &e.x happens to be the same as &e in this case.) Moving the contents to %eax sets the return value.



            In this case, the compiler needed the implicit this argument to foo(/* example* this */) to be able to find &e and therefore &e.x. In fact, inside a member function (that isn’t static), x, this->x and (*this).x all mean the same thing.






            share|improve this answer






























              up vote
              1
              down vote













              this is a pointer. It's like an implicit parameter that's part of every method. You could imagine using plain C functions and writing code like:



              Socket makeSocket(int port) { ... }
              void send(Socket *this, Value v) { ... }
              Value receive(Socket *this) { ... }

              Socket *mySocket = makeSocket(1234);
              send(mySocket, someValue); // The subject, `mySocket`, is passed in as a param called "this", explicitly
              Value newData = receive(socket);


              In C++, similar code might look like:



              mySocket.send(someValue); // The subject, `mySocket`, is passed in as a param called "this"
              Value newData = mySocket.receive();





              share|improve this answer





















                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                 

                draft saved


                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264848%2fis-the-this-pointer-just-a-compile-time-thing%23new-answer', 'question_page');
                }
                );

                Post as a guest
































                11 Answers
                11






                active

                oldest

                votes








                11 Answers
                11






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                64
                down vote



                accepted











                So is the this pointer just a compile time thing and not an actual pointer?




                It very much is a run time thing. It refers to the object on which the member function is invoked, naturally that object can exist at run time.



                What is a compile time thing is how name lookup works. When a compiler encounters x = X it must figure out what is this x that is being assigned. So it looks it up, and finds the member variable. Since this->x and x refer to the same thing, naturally you get the same assembly output.






                share|improve this answer





















                • Comments are not for extended discussion; this conversation has been moved to chat.
                  – Samuel Liew
                  8 hours ago















                up vote
                64
                down vote



                accepted











                So is the this pointer just a compile time thing and not an actual pointer?




                It very much is a run time thing. It refers to the object on which the member function is invoked, naturally that object can exist at run time.



                What is a compile time thing is how name lookup works. When a compiler encounters x = X it must figure out what is this x that is being assigned. So it looks it up, and finds the member variable. Since this->x and x refer to the same thing, naturally you get the same assembly output.






                share|improve this answer





















                • Comments are not for extended discussion; this conversation has been moved to chat.
                  – Samuel Liew
                  8 hours ago













                up vote
                64
                down vote



                accepted







                up vote
                64
                down vote



                accepted







                So is the this pointer just a compile time thing and not an actual pointer?




                It very much is a run time thing. It refers to the object on which the member function is invoked, naturally that object can exist at run time.



                What is a compile time thing is how name lookup works. When a compiler encounters x = X it must figure out what is this x that is being assigned. So it looks it up, and finds the member variable. Since this->x and x refer to the same thing, naturally you get the same assembly output.






                share|improve this answer













                So is the this pointer just a compile time thing and not an actual pointer?




                It very much is a run time thing. It refers to the object on which the member function is invoked, naturally that object can exist at run time.



                What is a compile time thing is how name lookup works. When a compiler encounters x = X it must figure out what is this x that is being assigned. So it looks it up, and finds the member variable. Since this->x and x refer to the same thing, naturally you get the same assembly output.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 2 days ago









                StoryTeller

                88.6k12177245




                88.6k12177245












                • Comments are not for extended discussion; this conversation has been moved to chat.
                  – Samuel Liew
                  8 hours ago


















                • Comments are not for extended discussion; this conversation has been moved to chat.
                  – Samuel Liew
                  8 hours ago
















                Comments are not for extended discussion; this conversation has been moved to chat.
                – Samuel Liew
                8 hours ago




                Comments are not for extended discussion; this conversation has been moved to chat.
                – Samuel Liew
                8 hours ago












                up vote
                23
                down vote













                It is an actual pointer, as the standard specifies it (§12.2.2.1):




                In the body of a non-static (12.2.1) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.




                this is actually implicit every time you reference a non-static member variable or member function within a class own code. It is also needed (either when implicit or explicit) because the compiler needs to tie back the function or the variable to an actual object at runtime.



                Using it explicitly is rarely useful, unless you need, for example, to disambiguate between a parameter and a member variable within a member function. Otherwise, without it the compiler will shadow the member variable with the parameter (See it live on Coliru).






                share|improve this answer



















                • 6




                  You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                  – Toby Speight
                  yesterday










                • It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                  – Martin Bonner
                  yesterday






                • 2




                  "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                  – Tezra
                  yesterday















                up vote
                23
                down vote













                It is an actual pointer, as the standard specifies it (§12.2.2.1):




                In the body of a non-static (12.2.1) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.




                this is actually implicit every time you reference a non-static member variable or member function within a class own code. It is also needed (either when implicit or explicit) because the compiler needs to tie back the function or the variable to an actual object at runtime.



                Using it explicitly is rarely useful, unless you need, for example, to disambiguate between a parameter and a member variable within a member function. Otherwise, without it the compiler will shadow the member variable with the parameter (See it live on Coliru).






                share|improve this answer



















                • 6




                  You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                  – Toby Speight
                  yesterday










                • It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                  – Martin Bonner
                  yesterday






                • 2




                  "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                  – Tezra
                  yesterday













                up vote
                23
                down vote










                up vote
                23
                down vote









                It is an actual pointer, as the standard specifies it (§12.2.2.1):




                In the body of a non-static (12.2.1) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.




                this is actually implicit every time you reference a non-static member variable or member function within a class own code. It is also needed (either when implicit or explicit) because the compiler needs to tie back the function or the variable to an actual object at runtime.



                Using it explicitly is rarely useful, unless you need, for example, to disambiguate between a parameter and a member variable within a member function. Otherwise, without it the compiler will shadow the member variable with the parameter (See it live on Coliru).






                share|improve this answer














                It is an actual pointer, as the standard specifies it (§12.2.2.1):




                In the body of a non-static (12.2.1) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.




                this is actually implicit every time you reference a non-static member variable or member function within a class own code. It is also needed (either when implicit or explicit) because the compiler needs to tie back the function or the variable to an actual object at runtime.



                Using it explicitly is rarely useful, unless you need, for example, to disambiguate between a parameter and a member variable within a member function. Otherwise, without it the compiler will shadow the member variable with the parameter (See it live on Coliru).







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited yesterday









                Toby Speight

                15.8k133965




                15.8k133965










                answered 2 days ago









                JBL

                9,52433567




                9,52433567








                • 6




                  You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                  – Toby Speight
                  yesterday










                • It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                  – Martin Bonner
                  yesterday






                • 2




                  "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                  – Tezra
                  yesterday














                • 6




                  You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                  – Toby Speight
                  yesterday










                • It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                  – Martin Bonner
                  yesterday






                • 2




                  "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                  – Tezra
                  yesterday








                6




                6




                You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                – Toby Speight
                yesterday




                You also need to explicitly write this-> when accessing a member of a non-dependent base type from a template member. Not often needed, and a good compiler will diagnose exactly when you forget it, but worth mentioning.
                – Toby Speight
                yesterday












                It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                – Martin Bonner
                yesterday




                It can also be very useful to write "this->" when developing with an IDE, because the IDE can then provide a list of members to select from. (Personally, I tend not to use an IDE, but if one chooses to, taking advantage of it seems sensible.)
                – Martin Bonner
                yesterday




                2




                2




                "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                – Tezra
                yesterday




                "Using it explicitly is rarely useful", from the compiler perspective, true; From a human perspective, some teams will enforce this as a style rule to prevent human-error introduced bugs.
                – Tezra
                yesterday










                up vote
                14
                down vote













                this always has to exist when you are in a non-static method. Whether you explicitly use it or not, you have to have a reference to the current instance, and this is what this gives you.



                In both cases, you are going to access memory through the this pointer. It's just that you can omit it in some cases.






                share|improve this answer























                • Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                  – Draco18s
                  2 days ago















                up vote
                14
                down vote













                this always has to exist when you are in a non-static method. Whether you explicitly use it or not, you have to have a reference to the current instance, and this is what this gives you.



                In both cases, you are going to access memory through the this pointer. It's just that you can omit it in some cases.






                share|improve this answer























                • Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                  – Draco18s
                  2 days ago













                up vote
                14
                down vote










                up vote
                14
                down vote









                this always has to exist when you are in a non-static method. Whether you explicitly use it or not, you have to have a reference to the current instance, and this is what this gives you.



                In both cases, you are going to access memory through the this pointer. It's just that you can omit it in some cases.






                share|improve this answer














                this always has to exist when you are in a non-static method. Whether you explicitly use it or not, you have to have a reference to the current instance, and this is what this gives you.



                In both cases, you are going to access memory through the this pointer. It's just that you can omit it in some cases.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 2 days ago

























                answered 2 days ago









                Matthieu Brucher

                5,4161128




                5,4161128












                • Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                  – Draco18s
                  2 days ago


















                • Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                  – Draco18s
                  2 days ago
















                Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                – Draco18s
                2 days ago




                Essentially, syntactical sugar (whether by inclusion or omission, its a shortcut).
                – Draco18s
                2 days ago










                up vote
                13
                down vote













                This is almost a duplicate of How do objects work in x86 at the assembly level?, where I comment the asm output of some examples, including showing which register the this pointer was passed in.





                In asm, this works exactly like a hidden first arg, so both the member-function foo::add(int) and the non-member add which takes an explicit foo* first arg compile to exactly the same asm.



                struct foo {
                int m;
                void add(int a); // not inline so we get a stand-alone definition emitted
                };

                void foo::add(int a) {
                this->m += a;
                }

                void add(foo *obj, int a) {
                obj->m += a;
                }


                On the Godbolt compiler explorer, compiling for x86-64 with the System V ABI (first arg in RDI, second in RSI), we get:



                # gcc8.2 -O3
                foo::add(int):
                add DWORD PTR [rdi], esi # memory-destination add
                ret
                add(foo*, int):
                add DWORD PTR [rdi], esi
                ret





                I use GCC 4.4.3




                That was released in January 2010, so it's missing nearly a decade of improvements to the optimizer, and to error messages. The gcc7 series has been out and stable for a while. Expect missed optimizations with such an old compiler, especially for modern instruction sets like AVX.






                share|improve this answer

























                  up vote
                  13
                  down vote













                  This is almost a duplicate of How do objects work in x86 at the assembly level?, where I comment the asm output of some examples, including showing which register the this pointer was passed in.





                  In asm, this works exactly like a hidden first arg, so both the member-function foo::add(int) and the non-member add which takes an explicit foo* first arg compile to exactly the same asm.



                  struct foo {
                  int m;
                  void add(int a); // not inline so we get a stand-alone definition emitted
                  };

                  void foo::add(int a) {
                  this->m += a;
                  }

                  void add(foo *obj, int a) {
                  obj->m += a;
                  }


                  On the Godbolt compiler explorer, compiling for x86-64 with the System V ABI (first arg in RDI, second in RSI), we get:



                  # gcc8.2 -O3
                  foo::add(int):
                  add DWORD PTR [rdi], esi # memory-destination add
                  ret
                  add(foo*, int):
                  add DWORD PTR [rdi], esi
                  ret





                  I use GCC 4.4.3




                  That was released in January 2010, so it's missing nearly a decade of improvements to the optimizer, and to error messages. The gcc7 series has been out and stable for a while. Expect missed optimizations with such an old compiler, especially for modern instruction sets like AVX.






                  share|improve this answer























                    up vote
                    13
                    down vote










                    up vote
                    13
                    down vote









                    This is almost a duplicate of How do objects work in x86 at the assembly level?, where I comment the asm output of some examples, including showing which register the this pointer was passed in.





                    In asm, this works exactly like a hidden first arg, so both the member-function foo::add(int) and the non-member add which takes an explicit foo* first arg compile to exactly the same asm.



                    struct foo {
                    int m;
                    void add(int a); // not inline so we get a stand-alone definition emitted
                    };

                    void foo::add(int a) {
                    this->m += a;
                    }

                    void add(foo *obj, int a) {
                    obj->m += a;
                    }


                    On the Godbolt compiler explorer, compiling for x86-64 with the System V ABI (first arg in RDI, second in RSI), we get:



                    # gcc8.2 -O3
                    foo::add(int):
                    add DWORD PTR [rdi], esi # memory-destination add
                    ret
                    add(foo*, int):
                    add DWORD PTR [rdi], esi
                    ret





                    I use GCC 4.4.3




                    That was released in January 2010, so it's missing nearly a decade of improvements to the optimizer, and to error messages. The gcc7 series has been out and stable for a while. Expect missed optimizations with such an old compiler, especially for modern instruction sets like AVX.






                    share|improve this answer












                    This is almost a duplicate of How do objects work in x86 at the assembly level?, where I comment the asm output of some examples, including showing which register the this pointer was passed in.





                    In asm, this works exactly like a hidden first arg, so both the member-function foo::add(int) and the non-member add which takes an explicit foo* first arg compile to exactly the same asm.



                    struct foo {
                    int m;
                    void add(int a); // not inline so we get a stand-alone definition emitted
                    };

                    void foo::add(int a) {
                    this->m += a;
                    }

                    void add(foo *obj, int a) {
                    obj->m += a;
                    }


                    On the Godbolt compiler explorer, compiling for x86-64 with the System V ABI (first arg in RDI, second in RSI), we get:



                    # gcc8.2 -O3
                    foo::add(int):
                    add DWORD PTR [rdi], esi # memory-destination add
                    ret
                    add(foo*, int):
                    add DWORD PTR [rdi], esi
                    ret





                    I use GCC 4.4.3




                    That was released in January 2010, so it's missing nearly a decade of improvements to the optimizer, and to error messages. The gcc7 series has been out and stable for a while. Expect missed optimizations with such an old compiler, especially for modern instruction sets like AVX.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 days ago









                    Peter Cordes

                    114k16173297




                    114k16173297






















                        up vote
                        9
                        down vote













                        After compilation, every symbol is just an address, so it can't be a run-time issue.



                        Any member symbol is compiled to an offset in the current class anyway, even if you didn't use this.



                        When name is used in C++ it can be one of the following.




                        • In the global namespace (like ::name), or in the current namespace, or in the used namespace (when using namespace ... been used)

                        • In the current class

                        • Local definition, in upper block

                        • Local definition, in current block


                        Therefore, when you write code, the compiler should scan each, in a manner to look for the symbol name, from the current block and up to the global namespace.



                        Using this->name helps the compiler to narrow the search for name to only look for it in the current class scope, meaning it skips local definitions, and if not found in class scope, do not look for it in the global scope.






                        share|improve this answer



























                          up vote
                          9
                          down vote













                          After compilation, every symbol is just an address, so it can't be a run-time issue.



                          Any member symbol is compiled to an offset in the current class anyway, even if you didn't use this.



                          When name is used in C++ it can be one of the following.




                          • In the global namespace (like ::name), or in the current namespace, or in the used namespace (when using namespace ... been used)

                          • In the current class

                          • Local definition, in upper block

                          • Local definition, in current block


                          Therefore, when you write code, the compiler should scan each, in a manner to look for the symbol name, from the current block and up to the global namespace.



                          Using this->name helps the compiler to narrow the search for name to only look for it in the current class scope, meaning it skips local definitions, and if not found in class scope, do not look for it in the global scope.






                          share|improve this answer

























                            up vote
                            9
                            down vote










                            up vote
                            9
                            down vote









                            After compilation, every symbol is just an address, so it can't be a run-time issue.



                            Any member symbol is compiled to an offset in the current class anyway, even if you didn't use this.



                            When name is used in C++ it can be one of the following.




                            • In the global namespace (like ::name), or in the current namespace, or in the used namespace (when using namespace ... been used)

                            • In the current class

                            • Local definition, in upper block

                            • Local definition, in current block


                            Therefore, when you write code, the compiler should scan each, in a manner to look for the symbol name, from the current block and up to the global namespace.



                            Using this->name helps the compiler to narrow the search for name to only look for it in the current class scope, meaning it skips local definitions, and if not found in class scope, do not look for it in the global scope.






                            share|improve this answer














                            After compilation, every symbol is just an address, so it can't be a run-time issue.



                            Any member symbol is compiled to an offset in the current class anyway, even if you didn't use this.



                            When name is used in C++ it can be one of the following.




                            • In the global namespace (like ::name), or in the current namespace, or in the used namespace (when using namespace ... been used)

                            • In the current class

                            • Local definition, in upper block

                            • Local definition, in current block


                            Therefore, when you write code, the compiler should scan each, in a manner to look for the symbol name, from the current block and up to the global namespace.



                            Using this->name helps the compiler to narrow the search for name to only look for it in the current class scope, meaning it skips local definitions, and if not found in class scope, do not look for it in the global scope.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited yesterday









                            Peter Mortensen

                            13.3k1983111




                            13.3k1983111










                            answered 2 days ago









                            SHR

                            5,48242240




                            5,48242240






















                                up vote
                                5
                                down vote













                                Here is a simple example how "this" could be useful during runtime:



                                #include <vector>
                                #include <string>
                                #include <iostream>

                                class A;
                                typedef std::vector<A*> News;
                                class A
                                {
                                public:
                                A(const char* n): name(n){}
                                std::string name;
                                void subscribe(News& n)
                                {
                                n.push_back(this);
                                }
                                };

                                int main()
                                {
                                A a1("Alex"), a2("Bob"), a3("Chris");
                                News news;

                                a1.subscribe(news);
                                a3.subscribe(news);

                                std::cout << "Subscriber:";
                                for(auto& a: news)
                                {
                                std::cout << " " << a->name;
                                }
                                return 0;
                                }





                                share|improve this answer

























                                  up vote
                                  5
                                  down vote













                                  Here is a simple example how "this" could be useful during runtime:



                                  #include <vector>
                                  #include <string>
                                  #include <iostream>

                                  class A;
                                  typedef std::vector<A*> News;
                                  class A
                                  {
                                  public:
                                  A(const char* n): name(n){}
                                  std::string name;
                                  void subscribe(News& n)
                                  {
                                  n.push_back(this);
                                  }
                                  };

                                  int main()
                                  {
                                  A a1("Alex"), a2("Bob"), a3("Chris");
                                  News news;

                                  a1.subscribe(news);
                                  a3.subscribe(news);

                                  std::cout << "Subscriber:";
                                  for(auto& a: news)
                                  {
                                  std::cout << " " << a->name;
                                  }
                                  return 0;
                                  }





                                  share|improve this answer























                                    up vote
                                    5
                                    down vote










                                    up vote
                                    5
                                    down vote









                                    Here is a simple example how "this" could be useful during runtime:



                                    #include <vector>
                                    #include <string>
                                    #include <iostream>

                                    class A;
                                    typedef std::vector<A*> News;
                                    class A
                                    {
                                    public:
                                    A(const char* n): name(n){}
                                    std::string name;
                                    void subscribe(News& n)
                                    {
                                    n.push_back(this);
                                    }
                                    };

                                    int main()
                                    {
                                    A a1("Alex"), a2("Bob"), a3("Chris");
                                    News news;

                                    a1.subscribe(news);
                                    a3.subscribe(news);

                                    std::cout << "Subscriber:";
                                    for(auto& a: news)
                                    {
                                    std::cout << " " << a->name;
                                    }
                                    return 0;
                                    }





                                    share|improve this answer












                                    Here is a simple example how "this" could be useful during runtime:



                                    #include <vector>
                                    #include <string>
                                    #include <iostream>

                                    class A;
                                    typedef std::vector<A*> News;
                                    class A
                                    {
                                    public:
                                    A(const char* n): name(n){}
                                    std::string name;
                                    void subscribe(News& n)
                                    {
                                    n.push_back(this);
                                    }
                                    };

                                    int main()
                                    {
                                    A a1("Alex"), a2("Bob"), a3("Chris");
                                    News news;

                                    a1.subscribe(news);
                                    a3.subscribe(news);

                                    std::cout << "Subscriber:";
                                    for(auto& a: news)
                                    {
                                    std::cout << " " << a->name;
                                    }
                                    return 0;
                                    }






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered 2 days ago









                                    Helmut Zeisel

                                    663




                                    663






















                                        up vote
                                        3
                                        down vote














                                        since I usually use it every single time I refer to a member variable or function.




                                        You always use this when you refer to a member variable or function. There is simply no other way to reach members. The only choice is implicit vs explicit notation.



                                        Let's go back to see how it was done before this to understand what this is.



                                        Without OOP:



                                        struct A {
                                        int x;
                                        };

                                        void foo(A* that) {
                                        bar(that->x)
                                        }


                                        With OOP but writing this explicitly



                                        struct A {
                                        int x;

                                        void foo(void) {
                                        bar(this->x)
                                        }
                                        };


                                        using shorter notation:



                                        struct A {
                                        int x;

                                        void foo(void) {
                                        bar(x)
                                        }
                                        };


                                        But the difference is only in source code. All are compiled to same thing. If you create a member method, the compiler will create a pointer argument for you and name it "this". If you omit this-> when referring to a member, the compiler is clever just enough to insert it for you most of the time. That's it. The only difference is 6 less letters in the source.



                                        Writing this explicitly makes sense when there is an ambiguity, namely another variable named just like your member variable:



                                        struct A {
                                        int x;

                                        A(int x) {
                                        this->x = x
                                        }
                                        };


                                        There are some instances, like __thiscall, where OO and non-OO code may end bit different in asm, but whenever the pointer is passed on stack and then optimized to a register or in ECX from the very beginning doesn't make it "not a pointer".






                                        share|improve this answer

























                                          up vote
                                          3
                                          down vote














                                          since I usually use it every single time I refer to a member variable or function.




                                          You always use this when you refer to a member variable or function. There is simply no other way to reach members. The only choice is implicit vs explicit notation.



                                          Let's go back to see how it was done before this to understand what this is.



                                          Without OOP:



                                          struct A {
                                          int x;
                                          };

                                          void foo(A* that) {
                                          bar(that->x)
                                          }


                                          With OOP but writing this explicitly



                                          struct A {
                                          int x;

                                          void foo(void) {
                                          bar(this->x)
                                          }
                                          };


                                          using shorter notation:



                                          struct A {
                                          int x;

                                          void foo(void) {
                                          bar(x)
                                          }
                                          };


                                          But the difference is only in source code. All are compiled to same thing. If you create a member method, the compiler will create a pointer argument for you and name it "this". If you omit this-> when referring to a member, the compiler is clever just enough to insert it for you most of the time. That's it. The only difference is 6 less letters in the source.



                                          Writing this explicitly makes sense when there is an ambiguity, namely another variable named just like your member variable:



                                          struct A {
                                          int x;

                                          A(int x) {
                                          this->x = x
                                          }
                                          };


                                          There are some instances, like __thiscall, where OO and non-OO code may end bit different in asm, but whenever the pointer is passed on stack and then optimized to a register or in ECX from the very beginning doesn't make it "not a pointer".






                                          share|improve this answer























                                            up vote
                                            3
                                            down vote










                                            up vote
                                            3
                                            down vote










                                            since I usually use it every single time I refer to a member variable or function.




                                            You always use this when you refer to a member variable or function. There is simply no other way to reach members. The only choice is implicit vs explicit notation.



                                            Let's go back to see how it was done before this to understand what this is.



                                            Without OOP:



                                            struct A {
                                            int x;
                                            };

                                            void foo(A* that) {
                                            bar(that->x)
                                            }


                                            With OOP but writing this explicitly



                                            struct A {
                                            int x;

                                            void foo(void) {
                                            bar(this->x)
                                            }
                                            };


                                            using shorter notation:



                                            struct A {
                                            int x;

                                            void foo(void) {
                                            bar(x)
                                            }
                                            };


                                            But the difference is only in source code. All are compiled to same thing. If you create a member method, the compiler will create a pointer argument for you and name it "this". If you omit this-> when referring to a member, the compiler is clever just enough to insert it for you most of the time. That's it. The only difference is 6 less letters in the source.



                                            Writing this explicitly makes sense when there is an ambiguity, namely another variable named just like your member variable:



                                            struct A {
                                            int x;

                                            A(int x) {
                                            this->x = x
                                            }
                                            };


                                            There are some instances, like __thiscall, where OO and non-OO code may end bit different in asm, but whenever the pointer is passed on stack and then optimized to a register or in ECX from the very beginning doesn't make it "not a pointer".






                                            share|improve this answer













                                            since I usually use it every single time I refer to a member variable or function.




                                            You always use this when you refer to a member variable or function. There is simply no other way to reach members. The only choice is implicit vs explicit notation.



                                            Let's go back to see how it was done before this to understand what this is.



                                            Without OOP:



                                            struct A {
                                            int x;
                                            };

                                            void foo(A* that) {
                                            bar(that->x)
                                            }


                                            With OOP but writing this explicitly



                                            struct A {
                                            int x;

                                            void foo(void) {
                                            bar(this->x)
                                            }
                                            };


                                            using shorter notation:



                                            struct A {
                                            int x;

                                            void foo(void) {
                                            bar(x)
                                            }
                                            };


                                            But the difference is only in source code. All are compiled to same thing. If you create a member method, the compiler will create a pointer argument for you and name it "this". If you omit this-> when referring to a member, the compiler is clever just enough to insert it for you most of the time. That's it. The only difference is 6 less letters in the source.



                                            Writing this explicitly makes sense when there is an ambiguity, namely another variable named just like your member variable:



                                            struct A {
                                            int x;

                                            A(int x) {
                                            this->x = x
                                            }
                                            };


                                            There are some instances, like __thiscall, where OO and non-OO code may end bit different in asm, but whenever the pointer is passed on stack and then optimized to a register or in ECX from the very beginning doesn't make it "not a pointer".







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered yesterday









                                            Agent_L

                                            3,1711620




                                            3,1711620






















                                                up vote
                                                2
                                                down vote













                                                Your machine does not know anything about class methods, they are normal functions under the hood.
                                                Hence methods have to be implemented by always passing a pointer to the current object, it's just implicit in C++, i.e. T Class::method(...) is just syntactic sugar for T Class_Method(Class* this, ...).



                                                Other languages like Python or Lua choose to make it explicit and modern object-oriented C APIs like Vulkan (unlike OpenGL) use a similar pattern.






                                                share|improve this answer

























                                                  up vote
                                                  2
                                                  down vote













                                                  Your machine does not know anything about class methods, they are normal functions under the hood.
                                                  Hence methods have to be implemented by always passing a pointer to the current object, it's just implicit in C++, i.e. T Class::method(...) is just syntactic sugar for T Class_Method(Class* this, ...).



                                                  Other languages like Python or Lua choose to make it explicit and modern object-oriented C APIs like Vulkan (unlike OpenGL) use a similar pattern.






                                                  share|improve this answer























                                                    up vote
                                                    2
                                                    down vote










                                                    up vote
                                                    2
                                                    down vote









                                                    Your machine does not know anything about class methods, they are normal functions under the hood.
                                                    Hence methods have to be implemented by always passing a pointer to the current object, it's just implicit in C++, i.e. T Class::method(...) is just syntactic sugar for T Class_Method(Class* this, ...).



                                                    Other languages like Python or Lua choose to make it explicit and modern object-oriented C APIs like Vulkan (unlike OpenGL) use a similar pattern.






                                                    share|improve this answer












                                                    Your machine does not know anything about class methods, they are normal functions under the hood.
                                                    Hence methods have to be implemented by always passing a pointer to the current object, it's just implicit in C++, i.e. T Class::method(...) is just syntactic sugar for T Class_Method(Class* this, ...).



                                                    Other languages like Python or Lua choose to make it explicit and modern object-oriented C APIs like Vulkan (unlike OpenGL) use a similar pattern.







                                                    share|improve this answer












                                                    share|improve this answer



                                                    share|improve this answer










                                                    answered yesterday









                                                    Trass3r

                                                    2,7501429




                                                    2,7501429






















                                                        up vote
                                                        2
                                                        down vote













                                                        "this" can also safeguard against shadowing by a function parameter, for example:



                                                        class Vector {
                                                        public:
                                                        double x,y,z;
                                                        void SetLocation(double x, double y, double z);
                                                        };

                                                        void Vector::SetLocation(double x, double y, double z) {
                                                        this->x = x; //Passed parameter assigned to member variable
                                                        this->y = y;
                                                        this->z = z;
                                                        }


                                                        (Obviously, writing such code is discouraged.)






                                                        share|improve this answer

















                                                        • 1




                                                          Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                          – Tezra
                                                          yesterday












                                                        • Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                          – Trass3r
                                                          16 hours ago















                                                        up vote
                                                        2
                                                        down vote













                                                        "this" can also safeguard against shadowing by a function parameter, for example:



                                                        class Vector {
                                                        public:
                                                        double x,y,z;
                                                        void SetLocation(double x, double y, double z);
                                                        };

                                                        void Vector::SetLocation(double x, double y, double z) {
                                                        this->x = x; //Passed parameter assigned to member variable
                                                        this->y = y;
                                                        this->z = z;
                                                        }


                                                        (Obviously, writing such code is discouraged.)






                                                        share|improve this answer

















                                                        • 1




                                                          Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                          – Tezra
                                                          yesterday












                                                        • Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                          – Trass3r
                                                          16 hours ago













                                                        up vote
                                                        2
                                                        down vote










                                                        up vote
                                                        2
                                                        down vote









                                                        "this" can also safeguard against shadowing by a function parameter, for example:



                                                        class Vector {
                                                        public:
                                                        double x,y,z;
                                                        void SetLocation(double x, double y, double z);
                                                        };

                                                        void Vector::SetLocation(double x, double y, double z) {
                                                        this->x = x; //Passed parameter assigned to member variable
                                                        this->y = y;
                                                        this->z = z;
                                                        }


                                                        (Obviously, writing such code is discouraged.)






                                                        share|improve this answer












                                                        "this" can also safeguard against shadowing by a function parameter, for example:



                                                        class Vector {
                                                        public:
                                                        double x,y,z;
                                                        void SetLocation(double x, double y, double z);
                                                        };

                                                        void Vector::SetLocation(double x, double y, double z) {
                                                        this->x = x; //Passed parameter assigned to member variable
                                                        this->y = y;
                                                        this->z = z;
                                                        }


                                                        (Obviously, writing such code is discouraged.)







                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered yesterday









                                                        Szak1

                                                        37539




                                                        37539








                                                        • 1




                                                          Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                          – Tezra
                                                          yesterday












                                                        • Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                          – Trass3r
                                                          16 hours ago














                                                        • 1




                                                          Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                          – Tezra
                                                          yesterday












                                                        • Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                          – Trass3r
                                                          16 hours ago








                                                        1




                                                        1




                                                        Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                        – Tezra
                                                        yesterday






                                                        Usually shadowing comes up as an issue when the member variable is being shadowed by an introduced local variable (where you normally aren't thinking of what is in the global scope), so use of this->x is encouraged to prevent such modification bugs.
                                                        – Tezra
                                                        yesterday














                                                        Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                        – Trass3r
                                                        16 hours ago




                                                        Yeah unfortunately -Wshadow is not enabled with -Wall. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                                                        – Trass3r
                                                        16 hours ago










                                                        up vote
                                                        2
                                                        down vote













                                                        if the compiler inlines a member function that is called with static rather than dynamic binding, it might be able to optimize away the this pointer. Take this simple example:



                                                        #include <iostream>

                                                        using std::cout;
                                                        using std::endl;

                                                        class example {
                                                        public:
                                                        int foo() const { return x; }
                                                        int foo(const int i) { return (x = i); }

                                                        private:
                                                        int x;
                                                        };

                                                        int main(void)
                                                        {
                                                        example e;
                                                        e.foo(10);
                                                        cout << e.foo() << endl;
                                                        }


                                                        GCC 7.3.0 with the -march=x86-64 -O -S flag is able to compile cout << e.foo() to three instructions:



                                                        movl    $10, %esi
                                                        leaq _ZSt4cout(%rip), %rdi
                                                        call _ZNSolsEi@PLT


                                                        This is a call to std::ostream::operator<<. Remember that cout << e.foo(); is syntactic sugar for std::ostream::operator<< (cout, e.foo());. And operator<<(int) could be written two ways: static operator<< (ostream&, int), as a non-member function, where the operand on the left is an explicit parameter, or operator<<(int), as a member function, where it’s implicitly this.



                                                        The compiler was able to deduce that e.foo() will always be the constant 10. Since the 64-bit x86 calling convention is to pass function arguments in registers, that compiles down to the single movl instruction, which sets the second function parameter to 10. The leaq instruction sets the first argument (which might be an explicit ostream& or the implicit this) to &cout. Then the program makes a call to the function.



                                                        In more complex cases, though—such as if you have a function taking an example& as a parameter—the compiler needs to look up this, as this is what tells the program which instance it’s working with, and therefore, which instance’s x data member to look up.



                                                        Consider this example:



                                                        class example {
                                                        public:
                                                        int foo() const { return x; }
                                                        int foo(const int i) { return (x = i); }

                                                        private:
                                                        int x;
                                                        };

                                                        int bar( const example& e )
                                                        {
                                                        return e.foo();
                                                        }


                                                        The function bar() gets compiled to a bit of boilerplate and the instruction:



                                                        movl    (%rdi), %eax
                                                        ret


                                                        You remember from the previous example that %rdi on x86-64 is the first function argument, the implicit this pointer for the call to e.foo(). Putting it in parentheses, (%rdi), means look up the variable at that location. (Since the only data in an example instance is x, &e.x happens to be the same as &e in this case.) Moving the contents to %eax sets the return value.



                                                        In this case, the compiler needed the implicit this argument to foo(/* example* this */) to be able to find &e and therefore &e.x. In fact, inside a member function (that isn’t static), x, this->x and (*this).x all mean the same thing.






                                                        share|improve this answer



























                                                          up vote
                                                          2
                                                          down vote













                                                          if the compiler inlines a member function that is called with static rather than dynamic binding, it might be able to optimize away the this pointer. Take this simple example:



                                                          #include <iostream>

                                                          using std::cout;
                                                          using std::endl;

                                                          class example {
                                                          public:
                                                          int foo() const { return x; }
                                                          int foo(const int i) { return (x = i); }

                                                          private:
                                                          int x;
                                                          };

                                                          int main(void)
                                                          {
                                                          example e;
                                                          e.foo(10);
                                                          cout << e.foo() << endl;
                                                          }


                                                          GCC 7.3.0 with the -march=x86-64 -O -S flag is able to compile cout << e.foo() to three instructions:



                                                          movl    $10, %esi
                                                          leaq _ZSt4cout(%rip), %rdi
                                                          call _ZNSolsEi@PLT


                                                          This is a call to std::ostream::operator<<. Remember that cout << e.foo(); is syntactic sugar for std::ostream::operator<< (cout, e.foo());. And operator<<(int) could be written two ways: static operator<< (ostream&, int), as a non-member function, where the operand on the left is an explicit parameter, or operator<<(int), as a member function, where it’s implicitly this.



                                                          The compiler was able to deduce that e.foo() will always be the constant 10. Since the 64-bit x86 calling convention is to pass function arguments in registers, that compiles down to the single movl instruction, which sets the second function parameter to 10. The leaq instruction sets the first argument (which might be an explicit ostream& or the implicit this) to &cout. Then the program makes a call to the function.



                                                          In more complex cases, though—such as if you have a function taking an example& as a parameter—the compiler needs to look up this, as this is what tells the program which instance it’s working with, and therefore, which instance’s x data member to look up.



                                                          Consider this example:



                                                          class example {
                                                          public:
                                                          int foo() const { return x; }
                                                          int foo(const int i) { return (x = i); }

                                                          private:
                                                          int x;
                                                          };

                                                          int bar( const example& e )
                                                          {
                                                          return e.foo();
                                                          }


                                                          The function bar() gets compiled to a bit of boilerplate and the instruction:



                                                          movl    (%rdi), %eax
                                                          ret


                                                          You remember from the previous example that %rdi on x86-64 is the first function argument, the implicit this pointer for the call to e.foo(). Putting it in parentheses, (%rdi), means look up the variable at that location. (Since the only data in an example instance is x, &e.x happens to be the same as &e in this case.) Moving the contents to %eax sets the return value.



                                                          In this case, the compiler needed the implicit this argument to foo(/* example* this */) to be able to find &e and therefore &e.x. In fact, inside a member function (that isn’t static), x, this->x and (*this).x all mean the same thing.






                                                          share|improve this answer

























                                                            up vote
                                                            2
                                                            down vote










                                                            up vote
                                                            2
                                                            down vote









                                                            if the compiler inlines a member function that is called with static rather than dynamic binding, it might be able to optimize away the this pointer. Take this simple example:



                                                            #include <iostream>

                                                            using std::cout;
                                                            using std::endl;

                                                            class example {
                                                            public:
                                                            int foo() const { return x; }
                                                            int foo(const int i) { return (x = i); }

                                                            private:
                                                            int x;
                                                            };

                                                            int main(void)
                                                            {
                                                            example e;
                                                            e.foo(10);
                                                            cout << e.foo() << endl;
                                                            }


                                                            GCC 7.3.0 with the -march=x86-64 -O -S flag is able to compile cout << e.foo() to three instructions:



                                                            movl    $10, %esi
                                                            leaq _ZSt4cout(%rip), %rdi
                                                            call _ZNSolsEi@PLT


                                                            This is a call to std::ostream::operator<<. Remember that cout << e.foo(); is syntactic sugar for std::ostream::operator<< (cout, e.foo());. And operator<<(int) could be written two ways: static operator<< (ostream&, int), as a non-member function, where the operand on the left is an explicit parameter, or operator<<(int), as a member function, where it’s implicitly this.



                                                            The compiler was able to deduce that e.foo() will always be the constant 10. Since the 64-bit x86 calling convention is to pass function arguments in registers, that compiles down to the single movl instruction, which sets the second function parameter to 10. The leaq instruction sets the first argument (which might be an explicit ostream& or the implicit this) to &cout. Then the program makes a call to the function.



                                                            In more complex cases, though—such as if you have a function taking an example& as a parameter—the compiler needs to look up this, as this is what tells the program which instance it’s working with, and therefore, which instance’s x data member to look up.



                                                            Consider this example:



                                                            class example {
                                                            public:
                                                            int foo() const { return x; }
                                                            int foo(const int i) { return (x = i); }

                                                            private:
                                                            int x;
                                                            };

                                                            int bar( const example& e )
                                                            {
                                                            return e.foo();
                                                            }


                                                            The function bar() gets compiled to a bit of boilerplate and the instruction:



                                                            movl    (%rdi), %eax
                                                            ret


                                                            You remember from the previous example that %rdi on x86-64 is the first function argument, the implicit this pointer for the call to e.foo(). Putting it in parentheses, (%rdi), means look up the variable at that location. (Since the only data in an example instance is x, &e.x happens to be the same as &e in this case.) Moving the contents to %eax sets the return value.



                                                            In this case, the compiler needed the implicit this argument to foo(/* example* this */) to be able to find &e and therefore &e.x. In fact, inside a member function (that isn’t static), x, this->x and (*this).x all mean the same thing.






                                                            share|improve this answer














                                                            if the compiler inlines a member function that is called with static rather than dynamic binding, it might be able to optimize away the this pointer. Take this simple example:



                                                            #include <iostream>

                                                            using std::cout;
                                                            using std::endl;

                                                            class example {
                                                            public:
                                                            int foo() const { return x; }
                                                            int foo(const int i) { return (x = i); }

                                                            private:
                                                            int x;
                                                            };

                                                            int main(void)
                                                            {
                                                            example e;
                                                            e.foo(10);
                                                            cout << e.foo() << endl;
                                                            }


                                                            GCC 7.3.0 with the -march=x86-64 -O -S flag is able to compile cout << e.foo() to three instructions:



                                                            movl    $10, %esi
                                                            leaq _ZSt4cout(%rip), %rdi
                                                            call _ZNSolsEi@PLT


                                                            This is a call to std::ostream::operator<<. Remember that cout << e.foo(); is syntactic sugar for std::ostream::operator<< (cout, e.foo());. And operator<<(int) could be written two ways: static operator<< (ostream&, int), as a non-member function, where the operand on the left is an explicit parameter, or operator<<(int), as a member function, where it’s implicitly this.



                                                            The compiler was able to deduce that e.foo() will always be the constant 10. Since the 64-bit x86 calling convention is to pass function arguments in registers, that compiles down to the single movl instruction, which sets the second function parameter to 10. The leaq instruction sets the first argument (which might be an explicit ostream& or the implicit this) to &cout. Then the program makes a call to the function.



                                                            In more complex cases, though—such as if you have a function taking an example& as a parameter—the compiler needs to look up this, as this is what tells the program which instance it’s working with, and therefore, which instance’s x data member to look up.



                                                            Consider this example:



                                                            class example {
                                                            public:
                                                            int foo() const { return x; }
                                                            int foo(const int i) { return (x = i); }

                                                            private:
                                                            int x;
                                                            };

                                                            int bar( const example& e )
                                                            {
                                                            return e.foo();
                                                            }


                                                            The function bar() gets compiled to a bit of boilerplate and the instruction:



                                                            movl    (%rdi), %eax
                                                            ret


                                                            You remember from the previous example that %rdi on x86-64 is the first function argument, the implicit this pointer for the call to e.foo(). Putting it in parentheses, (%rdi), means look up the variable at that location. (Since the only data in an example instance is x, &e.x happens to be the same as &e in this case.) Moving the contents to %eax sets the return value.



                                                            In this case, the compiler needed the implicit this argument to foo(/* example* this */) to be able to find &e and therefore &e.x. In fact, inside a member function (that isn’t static), x, this->x and (*this).x all mean the same thing.







                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited 17 hours ago

























                                                            answered yesterday









                                                            Davislor

                                                            8,22111126




                                                            8,22111126






















                                                                up vote
                                                                1
                                                                down vote













                                                                this is a pointer. It's like an implicit parameter that's part of every method. You could imagine using plain C functions and writing code like:



                                                                Socket makeSocket(int port) { ... }
                                                                void send(Socket *this, Value v) { ... }
                                                                Value receive(Socket *this) { ... }

                                                                Socket *mySocket = makeSocket(1234);
                                                                send(mySocket, someValue); // The subject, `mySocket`, is passed in as a param called "this", explicitly
                                                                Value newData = receive(socket);


                                                                In C++, similar code might look like:



                                                                mySocket.send(someValue); // The subject, `mySocket`, is passed in as a param called "this"
                                                                Value newData = mySocket.receive();





                                                                share|improve this answer

























                                                                  up vote
                                                                  1
                                                                  down vote













                                                                  this is a pointer. It's like an implicit parameter that's part of every method. You could imagine using plain C functions and writing code like:



                                                                  Socket makeSocket(int port) { ... }
                                                                  void send(Socket *this, Value v) { ... }
                                                                  Value receive(Socket *this) { ... }

                                                                  Socket *mySocket = makeSocket(1234);
                                                                  send(mySocket, someValue); // The subject, `mySocket`, is passed in as a param called "this", explicitly
                                                                  Value newData = receive(socket);


                                                                  In C++, similar code might look like:



                                                                  mySocket.send(someValue); // The subject, `mySocket`, is passed in as a param called "this"
                                                                  Value newData = mySocket.receive();





                                                                  share|improve this answer























                                                                    up vote
                                                                    1
                                                                    down vote










                                                                    up vote
                                                                    1
                                                                    down vote









                                                                    this is a pointer. It's like an implicit parameter that's part of every method. You could imagine using plain C functions and writing code like:



                                                                    Socket makeSocket(int port) { ... }
                                                                    void send(Socket *this, Value v) { ... }
                                                                    Value receive(Socket *this) { ... }

                                                                    Socket *mySocket = makeSocket(1234);
                                                                    send(mySocket, someValue); // The subject, `mySocket`, is passed in as a param called "this", explicitly
                                                                    Value newData = receive(socket);


                                                                    In C++, similar code might look like:



                                                                    mySocket.send(someValue); // The subject, `mySocket`, is passed in as a param called "this"
                                                                    Value newData = mySocket.receive();





                                                                    share|improve this answer












                                                                    this is a pointer. It's like an implicit parameter that's part of every method. You could imagine using plain C functions and writing code like:



                                                                    Socket makeSocket(int port) { ... }
                                                                    void send(Socket *this, Value v) { ... }
                                                                    Value receive(Socket *this) { ... }

                                                                    Socket *mySocket = makeSocket(1234);
                                                                    send(mySocket, someValue); // The subject, `mySocket`, is passed in as a param called "this", explicitly
                                                                    Value newData = receive(socket);


                                                                    In C++, similar code might look like:



                                                                    mySocket.send(someValue); // The subject, `mySocket`, is passed in as a param called "this"
                                                                    Value newData = mySocket.receive();






                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered 16 hours ago









                                                                    Alexander

                                                                    30.1k44474




                                                                    30.1k44474






























                                                                         

                                                                        draft saved


                                                                        draft discarded



















































                                                                         


                                                                        draft saved


                                                                        draft discarded














                                                                        StackExchange.ready(
                                                                        function () {
                                                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53264848%2fis-the-this-pointer-just-a-compile-time-thing%23new-answer', 'question_page');
                                                                        }
                                                                        );

                                                                        Post as a guest




















































































                                                                        Popular posts from this blog

                                                                        How to change which sound is reproduced for terminal bell?

                                                                        Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                                                                        Can I use Tabulator js library in my java Spring + Thymeleaf project?