2016-11-16 1 views
39

生ポインタを使用した場合と比較して、オーバーヘッドがないという印象を常に受け​​ていました。しかし、g++ -std=c++14 -O3unique_ptrのインスタンス化がrawポインタより大きなバイナリにコンパイルされるのはなぜですか?

#include <memory> 

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

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

には、次のアセンブリを作成し、次のコードをコンパイル:

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*) 

なぜsmart_pointer()のほぼ3倍raw_pointer()などのための出力?

+0

カウンタがあり、おそらくオーバーヘッドがあります。おそらくvtable –

+3

私は実際には全体が完全に離れて最適化されていないことに驚いています。 – SergeyA

+2

@ SergeyAそれはclangである。 –

答えて

53

std::make_unique<int[]>(100)を行うvalue initializationnew int[100]ながら行うdefault initializationために - 最初の場合、第2の場合に初期化されていない要素が残っている間に、要素は、(intために)0に初期化されています。試してみてください:

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

std::unique_ptrと同じ出力が得られます。

std::make_unique<int[]>(100)と等価であると述べている、例えばthisを参照してください:

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

あなたはstd::unique_ptrと非初期化配列をしたい場合は、あなたがを使用することができます。

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

コメントに@Ruslanで述べたように、ベットの違いに注意してくださいween std::make_unique()およびstd::unique_ptr() - Differences between std::make_unique and std::unique_ptrを参照してください。

+0

私はそうかもしれないと思った。初期化されていない配列を指し示す 'unique_ptr'を作成する方法はありますか? –

+2

@AlessandroPower 'std :: unique_ptr (新しいint [100])'。 – Holt

+3

@AlessandroPowerだが、[std :: make_uniqueとstd :: unique_ptrの相違点](http://stackoverflow.com/q/22571202/673852)に注意してください。 – Ruslan

関連する問題