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



我一再听说std::move(t)或多或少只是static_cast<T&&>(t)的一种奇特表达方式,不会生成任何指令。当我现在在godbolt上玩std::move时,为了更好地理解移动语义,我看到它确实(或者至少可能(生成指令。在本例中,

#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));
}

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

有人能给我解释一下吗?我不太清楚这个std::remove_reference<S&>::type&& std::move<S&>(S&)函数应该做什么,也不太清楚为什么会有这种明显的收缩。

对于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&)

foo(std::move(s));

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

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

leaq    12(%rsp), %rdi
call    foo(S const&)

编译时没有进行优化。因此,您可以准确地看到所写的内容,而无需任何简化或内联函数的尝试。

生成的代码大致等于type&& foo(type& x) { return x; }将生成的代码,move就是这样做的。

研究在没有打开优化的情况下生成的程序集是徒劳的。

相关内容

  • 没有找到相关文章

最新更新