为什么 std::move 在这里生成指令?

Elm*_*der 1 c++ move std c++11

我一次又一次听到这std::move(t)或多或少只是一种奇特的说法static_cast<T&&>(t),不会产生任何指示。当我现在std::move为了更好地理解移动语义而使用 godbolt 时,我发现它确实(或至少可能)生成指令。在这个例子中

#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));
}
Run Code Online (Sandbox Code Playgroud)

foo导致以下汇编输出的调用

        ; ... 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
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释一下吗?我不太明白这个std::remove_reference<S&>::type&& std::move<S&>(S&)函数应该做什么,以及为什么与通常所说的有明显的缩减。

ala*_*ner 6

std::remove_reference<S&>::type&& std::move<S&>(S&) Josuttis 在他的 C++ 移动语义中解释了这一点。

基本上它的作用与类型特征类似,static_cast<T&&>但具有类型特征的手段。它允许传入任何值类别(因此,左值或右值引用),然后它会切断引用部分并应用于右值引用部分。至于额外的说明:任何优化器都应该内联这些调用。

关闭优化并foo定义为void foo(const S& s);减少噪音:

foo(static_cast<S&&>(s));

        leaq    -4(%rbp), %rax
        movq    %rax, %rdi
        call    foo(S const&)
Run Code Online (Sandbox Code Playgroud)

foo(std::move(s));

        leaq    -4(%rbp), %rax
        movq    %rax, %rdi
        call    std::remove_reference<S&>::type&& std::move<S&>(S&)
        movq    %rax, %rdi
Run Code Online (Sandbox Code Playgroud)

对于-O1,两者的结果相同:

        leaq    12(%rsp), %rdi
        call    foo(S const&)
Run Code Online (Sandbox Code Playgroud)