复制引用会创建原始变量的副本(原始变量和新变量位于不同的区域),移动局部变量则将局部变量转换为rvalue(同样,原始变量和新变量位于不同的区域)。
从编译器的角度来看,
move
可能(并且确实)更快:
#include <string>
void MyClass(std::string title){
std::string title2 = std::move(title);
}
翻译为:
MyClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >): # @MyClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
sub rsp, 40
mov rax, rdi
lea rcx, [rsp + 24]
mov qword ptr [rsp + 8], rcx
mov rdi, qword ptr [rdi]
lea rdx, [rax + 16]
cmp rdi, rdx
je .LBB0_1
mov qword ptr [rsp + 8], rdi
mov rsi, qword ptr [rax + 16]
mov qword ptr [rsp + 24], rsi
jmp .LBB0_3
.LBB0_1:
movups xmm0, xmmword ptr [rdi]
movups xmmword ptr [rcx], xmm0
mov rdi, rcx
.LBB0_3:
mov rsi, qword ptr [rax + 8]
mov qword ptr [rsp + 16], rsi
mov qword ptr [rax], rdx
mov qword ptr [rax + 8], 0
mov byte ptr [rax + 16], 0
cmp rdi, rcx
je .LBB0_5
call operator delete(void*)
.LBB0_5:
add rsp, 40
ret
然而,
void MyClass(std::string& title){
std::string title = title
}
生成更大的代码(GCC类似):
MyClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&): # @MyClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
push r15
push r14
push rbx
sub rsp, 48
lea r15, [rsp + 32]
mov qword ptr [rsp + 16], r15
mov r14, qword ptr [rdi]
mov rbx, qword ptr [rdi + 8]
test r14, r14
jne .LBB0_2
test rbx, rbx
jne .LBB0_11
.LBB0_2:
mov qword ptr [rsp + 8], rbx
mov rax, r15
cmp rbx, 16
jb .LBB0_4
lea rdi, [rsp + 16]
lea rsi, [rsp + 8]
xor edx, edx
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long)
mov qword ptr [rsp + 16], rax
mov rcx, qword ptr [rsp + 8]
mov qword ptr [rsp + 32], rcx
.LBB0_4:
test rbx, rbx
je .LBB0_8
cmp rbx, 1
jne .LBB0_7
mov cl, byte ptr [r14]
mov byte ptr [rax], cl
jmp .LBB0_8
.LBB0_7:
mov rdi, rax
mov rsi, r14
mov rdx, rbx
call memcpy
.LBB0_8:
mov rax, qword ptr [rsp + 8]
mov qword ptr [rsp + 24], rax
mov rcx, qword ptr [rsp + 16]
mov byte ptr [rcx + rax], 0
mov rdi, qword ptr [rsp + 16]
cmp rdi, r15
je .LBB0_10
call operator delete(void*)
.LBB0_10:
add rsp, 48
pop rbx
pop r14
pop r15
ret
.LBB0_11:
mov edi, offset .L.str
call std::__throw_logic_error(char const*)
.L.str:
.asciz "basic_string::_M_construct null not valid"
所以,在这种情况下,std::move
更好。
std::string
引入了COW技术,那么第一个选项就会有很好的理由。 - MansoorMyClass::MyClass(std::string title_) : title{std::move(title_)} {}
。 - Eljay