考虑
struct A {
int *ptr;
A() : ptr(new int()) { }
A(A &&o) : ptr(o.release()) { }
~A() {
if (ptr)
delete ptr;
}
int *release() {
return std::exchange(ptr, nullptr);
}
};
相当于简单的 std::unique_ptr
,那么考虑下面的情况
A make();
void store(int *);
inline A foo() {
A a = make();
return FOO(a);
}
void bar() {
A a = foo();
store(a.release());
}
FOO
为 std::move
时编译结果如下(clang 11.0.1, O2)
bar(): # @bar()
pushq %rax
movq %rsp, %rdi
callq make()
movq (%rsp), %rdi
callq store(int*)
popq %rax
retq
FOO
为空时编译结果如下(条件同上)
bar(): # @bar()
pushq %rbx
subq $16, %rsp
leaq 8(%rsp), %rdi
callq make()
movq 8(%rsp), %rdi
movq $0, 8(%rsp)
callq store(int*)
movq 8(%rsp), %rdi
testq %rdi, %rdi
je .LBB0_3
callq operator delete(void*)
.LBB0_3:
addq $16, %rsp
popq %rbx
retq
movq %rax, %rbx
movq 8(%rsp), %rdi
testq %rdi, %rdi
je .LBB0_6
callq operator delete(void*)
.LBB0_6:
movq %rbx, %rdi
callq _Unwind_Resume
发生什么事了呢,见 Escape analysis hates copy elision
涉及了 NRVO (copy elision), escape analysis