简体   繁体   中英

return value Vs reference (in assembly)

After taking a look at a few questions (and answers) regarding this topic, I tried the below simple code in godbolt .

#include <iostream>


class TwoInts
{
public:
    TwoInts( ) = default;

    const int& getAByRef( ) const;

    int getAByVal( ) const;

private:
    int a;
    int b;
};

const int& TwoInts::getAByRef( ) const
{
    return a;
}

int TwoInts::getAByVal( ) const
{
    return a;
}


int main( )
{
    TwoInts ti;

    const int& num1 { ti.getAByRef( ) };
    const int num2 { ti.getAByVal( ) };

    //std::cout << num1 << ' ' << num2 << '\n';
}

Now I see different codes generated for the two member functions getAByRef and getAByVal :

TwoInts::getAByRef() const:
        mov     rax, rdi
        ret
TwoInts::getAByVal() const:
        mov     eax, DWORD PTR [rdi]
        ret

I would appreciate it if someone could explain what those two different assembly instructions are doing?

Each member function gets this pointer as an implicit argument. In ABI used by that particular compiler ( Itanium ABI , not to be confused with Itanium architecture), this is passed as the first argument in the rdi register and a value is returned (if it's trivial, and here it is) in the rax ( eax ) register.

In the first case, when you return a by reference, you're actually returning an address of a . a is the first member, so its address is the same as that of the object, ie this . Hence, you just set rax to rdi .

In the second case, when you return a by value, you need to do actual dereferencing. That's what DWORD PTR [rdi] is doing. DWORD PTR means that you want to fetch 4 bytes ( sizeof(int) ).

If you put some data member before a , you'll see an additional offset added to rdi .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM