https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98840
Bug ID: 98840 Summary: Why does baz call the delete operator for moved unique_ptr Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: dmitriy.ovdienko at gmail dot com Target Milestone: --- I'm trying to evaluate the overhead of the `unique_ptr` and I do not understand why does Gcc execute the destructor of the `unique_ptr` passed by value? Let's assume we have two examples of code: C style: ``` #include <memory> void foo(int* ptr); void baz(int value) { int* ptr = new int(value); try { foo(ptr); } catch(...) { delete ptr; throw; } } ``` The asm (/O3): ``` baz(int): push rbp push rbx mov ebx, edi mov edi, 4 sub rsp, 8 call operator new(unsigned long) mov DWORD PTR [rax], ebx mov rdi, rax mov rbp, rax call foo(int*) add rsp, 8 pop rbx pop rbp ret mov rdi, rax jmp .L2 baz(int) [clone .cold]: .L2: call __cxa_begin_catch mov esi, 4 mov rdi, rbp call operator delete(void*, unsigned long) call __cxa_rethrow mov rbp, rax call __cxa_end_catch mov rdi, rbp call _Unwind_Resume ``` And C++ style ``` #include <memory> void foo(std::unique_ptr<int> ptr); void baz(int value) { foo(std::make_unique<int>(value)); } ``` The asm (/O3) ``` baz(int): push rbp push rbx mov ebx, edi mov edi, 4 sub rsp, 24 call operator new(unsigned long) lea rdi, [rsp+8] mov DWORD PTR [rax], ebx mov QWORD PTR [rsp+8], rax call foo(std::unique_ptr<int, std::default_delete<int> >) mov rdi, QWORD PTR [rsp+8] test rdi, rdi je .L1 mov esi, 4 call operator delete(void*, unsigned long) <<<<<< Here, why do we need to call the delete operator. It is `foo` who is responsible for that .L1: add rsp, 24 pop rbx pop rbp ret mov rbp, rax jmp .L3 baz(int) [clone .cold]: ```