mercredi 13 avril 2022

Why is std::move generating instructions here?

I heard time and again that std::move(t) is more or less only a fancy way of saying static_cast<T&&>(t) and would not generate any instructions. When I was playing around now with std::move on godbolt in order to better understand move semantics I saw that it does (or at least may) generate instructions. In this example

#include <iostream>
using namespace std;

struct S {
    S() { cout << "default ctor" << endl; }
    S(S&& s) {
        i = s.i;
        s.i = 0;
        cout << "move ctor" << endl;
    }
    int i;
};

void foo(S s) { cout << "Foo called with " << s.i << endl; }

int main() {
    S s;
    foo(static_cast<S&&>(s));
    foo(std::move(s));
}

the calls to foo lead to the following assembly output

        ; ... snip ...
        lea     rdi, [rbp - 16]
        lea     rsi, [rbp - 8]
        call    S::S(S&&) [base object constructor]
        lea     rdi, [rbp - 16]
        call    foo(S)
        lea     rdi, [rbp - 8]
        call    std::remove_reference<S&>::type&& std::move<S&>(S&)
        lea     rdi, [rbp - 24]
        mov     rsi, rax
        call    S::S(S&&) [base object constructor]
        lea     rdi, [rbp - 24]
        call    foo(S)
        ; ... snip ...
std::remove_reference<S&>::type&& std::move<S&>(S&): # @std::remove_reference<S&>::type&& std::move<S&>(S&)
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     rax, qword ptr [rbp - 8]
        pop     rbp
        ret

Can someone please explain this to me? I can't much sense of what this std::remove_reference<S&>::type&& std::move<S&>(S&) function is supposed to do and why there is this apparent contraction to what's commonly told.

Aucun commentaire:

Enregistrer un commentaire