为什么 std::move 在这里生成指令?
我一次又一次听到std :: move(t)
或多或少是一种奇特的说法static_cast< t&&>(t)
没有生成任何说明。 当我现在使用std :: Move
在Godbolt上玩耍时,为了更好地理解移动语义,我看到它 dos (或至少可以)生成说明。在此示例中,
#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&lt; s&amp; :: type&amp;&amp;&amp; std :: move&lt; s&amp;&gt;(s&amp;)
函数应该做,以及为什么对通常所讲的内容有明显的收缩。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
至于
std :: remove_reference&lt; s&amp; :: type&amp;&amp; std :: move&lt; s&amp;&gt;(s&amp;)
Josuttis在他的C ++移动语义中解释了这一点。
基本上,它的作用类似于
static_cast&lt; t&amp;&amp;&gt;
,但具有类型特征的方式。它允许将任何值类别传递到中(因此,lvalue或rvalue参考),然后切断参考部分并适用于rvalue-ref One。至于额外的说明:任何优化器都应将这些呼叫内联。关闭优化和
定义为
void foo(const s&amp; s);
降低噪声:foo(static_cast&lt; s&amp;&amp;&amp;&gt;(s s );
foo(std :: move(s));
带有
-O1
,两者都会相同:As for
std::remove_reference<S&>::type&& std::move<S&>(S&)
Josuttis explains this in his C++ move semantics.
Basically what it does is similar to
static_cast<T&&>
but with the means of type traits. It allows any value category to be passed in (thus, either lvalue or rvalue reference) then it cuts off the reference part and applies to rvalue-ref one. As for the extra instructions: any optimizer should inline those calls anyway.With optimization turned off and
foo
defined asvoid foo(const S& s);
to reduce noise:foo(static_cast<S&&>(s));
foo(std::move(s));
With
-O1
, both result in the same:您正在编译而没有优化。因此,您可以准确地看到所写的内容,而无需尝试简化或内联函数。
生成的代码大致相当于
type&& foo(type&x) { 返回 x; }
会生成,这就是move
的作用。研究没有打开优化生成的程序集是徒劳的。
You are compiling without optimisations. So you see exactly what is written without any attempt to simplify or inline functions.
Generated code is roughly eqivalent to what
type&& foo(type& x) { return x; }
would generate, which is whatmove
does.Studying assembly generated without optimisations turned on is exercise in futility.