user19528914
user19528914

Reputation: 11

Why is the object prefix converted to function argument?

In the learncpp article about the hidden this pointer, the author mentioned that the compiler converts the object prefix to an argument passed by address to the function.

In the example:

simple.setID(2);

Will be converted to:

setID(&simple, 2); // note that simple has been changed from an object prefix to a function argument!

Why does the compiler do this? I've tried searching other documentation about it but couldn't find any. I've asked other people but they say it is a mistake or the compiler doesn't do that.

I have a second question on this topic. Let's go back to the example:

simple.setID(2); //Will be converted to setID(&simple, 2);

If the compiler converts it, won't it just look exactly like a function that has a name of setID and has two parameters?

void setID(MyClass* obj, int id) {
     return;
}


int main() {
    MyClass simple;
    simple.setID(2); //Will be converted to setID(&simple, 2);
    setID(&simple, 2);
    
}

Line 6 and 7 would look exactly the same.

Upvotes: 0

Views: 112

Answers (1)

t.niese
t.niese

Reputation: 40852

object prefix to an argument passed by address to the function

This refers to how implementations use to translate it to machine code (but they could do it any other way)

Why does the compiler do this?

In some way, you need to be able to refer to the object in the called member function, and one way is to just handle it like an argument.

If the compiler converts it, won't it just look exactly like a function that has a name of setID and has two parameters?

If you have this code:

struct Test {
    int v = 0;
    Test(int v ) : v(v) {

    }
    void test(int a) {
        int v = this->v;
        int r = a;
    } 
};

void test(Test* t, int a) {
    int v = t->v;
    int r = a + v;

}

int main() {
    Test a(2);
    a.test(1);
    test(&a, 1);

    return 0;
}

gcc-12 will create this assembly code (for x86 and if optimizations are turned off):

Test::Test(int) [base object constructor]:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        mov     rax, QWORD PTR [rbp-8]
        mov     edx, DWORD PTR [rbp-12]
        mov     DWORD PTR [rax], edx
        nop
        pop     rbp
        ret
Test::test(int a):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     DWORD PTR [rbp-28], esi
// int v = this->v;
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     DWORD PTR [rbp-4], eax
// int r = a;
        mov     eax, DWORD PTR [rbp-28]
        mov     DWORD PTR [rbp-8], eax
// end of function
        nop
        pop     rbp
        ret
test(Test* t, int a):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     DWORD PTR [rbp-28], esi
// int v = t->v;
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     DWORD PTR [rbp-4], eax
// int r = a + v;
        mov     edx, DWORD PTR [rbp-28]
        mov     eax, DWORD PTR [rbp-4]
        add     eax, edx
        mov     DWORD PTR [rbp-8], eax
// end of function
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        lea     rax, [rbp-4]
        mov     esi, 2
        mov     rdi, rax
        call    Test::Test(int) [complete object constructor]
// a.test(1);
        lea     rax, [rbp-4]
        mov     esi, 1
        mov     rdi, rax
        call    Test::test(int)
// test(&a, 1);
        lea     rax, [rbp-4]
        mov     esi, 1
        mov     rdi, rax
        call    test(Test*, int)
// end of main
        mov     eax, 0
        leave
        ret

So the machine code generated with no optimizations, looks identical for test(&a, 1) and a.test(1). And that's what the statement refers to.

But again that is an implementation detail how the compiler translates c++ to machine code, and not related to c++ itself.

Upvotes: 1

Related Questions