Please see: https://godbolt.org/z/4fqqMbebh.
struct Ptr {
int* x;
};
int* custom_struct(Ptr p) {
return p.x;
}
int* unique_ptr(std::unique_ptr<int> x) {
return x.get();
}
yields
custom_struct(Ptr):
mov rax, rdi
ret
unique_ptr(std::unique_ptr<int, std::default_delete<int> >):
mov rax, QWORD PTR [rdi]
ret
I was under the impression that unique_ptr’s memory layout is the same as the struct I have defined here. Could somebody explain why the unique_ptr access loads from memory (i.e. [rdi]) whereas the custom struct case can simply load rdi (what I expected unique_ptr to look like)?
2
std::unique_ptr
has a non-trivial destructor. This implies that the compiler is not allowed to introduce any temporary object when passing to the function per C++ standard. As a consequence std::unique_ptr
can’t be passed in a register, which would require performing a disallowed copy if the std::unique_ptr
is constructed on the call site from a prvalue expression.
What you see here is that your type with trivial destructor is passed by register, while std::unique_ptr
is passed on the stack.