Alessandro Power Alessandro Power - 24 days ago 9
C++ Question

Why does unique_ptr instantiation compile to larger binary than raw pointer?

I was always under the impression that a

std::unique_ptr
had no overhead compared to using a raw pointer. However, compiling the following code

#include <memory>

void raw_pointer() {
int* p = new int[100];
delete[] p;
}

void smart_pointer() {
auto p = std::make_unique<int[]>(100);
}


with
g++ -std=c++14 -O3
produces the following assembly:

raw_pointer():
sub rsp, 8
mov edi, 400
call operator new[](unsigned long)
add rsp, 8
mov rdi, rax
jmp operator delete[](void*)
smart_pointer():
sub rsp, 8
mov edi, 400
call operator new[](unsigned long)
lea rdi, [rax+8]
mov rcx, rax
mov QWORD PTR [rax], 0
mov QWORD PTR [rax+392], 0
mov rdx, rax
xor eax, eax
and rdi, -8
sub rcx, rdi
add ecx, 400
shr ecx, 3
rep stosq
mov rdi, rdx
add rsp, 8
jmp operator delete[](void*)


Why is the output for
smart_pointer()
almost three times as large as
raw_pointer()
?

Answer

Because std::make_unique<int[]>(100) performs value initialization while new int[100] performs default initialization - In the first case, elements are 0-initialized (for int), while in the second case elements are left uninitialized. Try:

int *p = new int[100]();

And you'll get the same output as with the std::unique_ptr.

See this for instance, which states that std::make_unique<int[]>(100) is equivalent to:

std::unique_ptr<T>(new int[100]())

If you want a non-initialized array with std::unique_ptr, you could use:

std::unique_ptr<int[]>(new int[100]);