std::unique_ptr
たとえば、配列をサポートしています。
std::unique_ptr<int[]> p(new int[10]);
しかし、それは必要ですか?std::vector
おそらくorを使用する方が便利std::array
です。
その構造の用途はありますか?
std::unique_ptr
たとえば、配列をサポートしています。
std::unique_ptr<int[]> p(new int[10]);
しかし、それは必要ですか?std::vector
おそらくorを使用する方が便利std::array
です。
その構造の用途はありますか?
トレードオフがあり、必要なものに一致するソリューションを選択します。私の頭の上から:
初期サイズ
vector
unique_ptr<T[]>
実行時にサイズを指定できるようにするarray
サイズはコンパイル時にのみ指定できますサイズ変更
array
サイズ変更を許可しunique_ptr<T[]>
ないvector
する保管所
vector
unique_ptr<T[]>
オブジェクトの外部(通常はヒープ上)にデータを保存しますarray
データをオブジェクトに直接保存しますコピー中
array
vector
コピーを許可するunique_ptr<T[]>
コピーを許可しませんスワップ/移動
vector
unique_ptr<T[]>
O(1) 回の操作とswap
移動操作があるarray
O(n) 回swap
の移動操作があり、n は配列内の要素の数です。ポインタ/参照/イテレータの無効化
array
オブジェクトが生きている間、たとえswap()
unique_ptr<T[]>
イテレータはありません。swap()
ポインタと参照は、オブジェクトが生きている間だけ無効化されます。(スワップ後、ポインターはスワップした配列を指しているため、その意味ではまだ「有効」です。)vector
再割り当てのポインター、参照、および反復子を無効にする可能性があります (また、再割り当てが特定の操作でのみ発生する可能性があることを保証します)。コンセプトとアルゴリズムとの互換性
array
両方ともvector
コンテナですunique_ptr<T[]>
コンテナではありません認めざるを得ませんが、これはポリシーベースの設計によるリファクタリングの機会のように見えます。
a を使用する理由の 1 つは、配列の値を初期化unique_ptr
する実行時のコストを払いたくない場合です。
std::vector<char> vec(1000000); // allocates AND value-initializes 1000000 chars
std::unique_ptr<char[]> p(new char[1000000]); // allocates storage for 1000000 chars
std::vector
コンストラクターはstd::vector::resize()
値を初期化しますT
が、POD のnew
場合はそうしません。T
C++11 および std::vector コンストラクターの値初期化オブジェクトを参照してください。
vector::reserve
ここでは代替ではないことに注意してください: Is access the raw pointer after std::vector::reserve safe?
malloc
これは、C プログラマーが を選択するのと同じ理由calloc
です。
std::vector
および とは対照的にstd::array
、std::unique_ptr
は NULL ポインターを所有できます。
これは、配列または NULL を予期する C API を使用する場合に便利です。
void legacy_func(const int *array_or_null);
void some_func() {
std::unique_ptr<int[]> ptr;
if (some_condition) {
ptr.reset(new int[10]);
}
legacy_func(ptr.get());
}
一部のWindows Win32 API呼び出しで一般的なパターンを見つけることがstd::unique_ptr<T[]>
できます。たとえば、一部の Win32 API を呼び出すときに出力バッファーの大きさが正確にわからない場合 (内部にデータを書き込む場合)、 を使用すると便利です。そのバッファ):
// Buffer dynamically allocated by the caller, and filled by some Win32 API function.
// (Allocation will be made inside the 'while' loop below.)
std::unique_ptr<BYTE[]> buffer;
// Buffer length, in bytes.
// Initialize with some initial length that you expect to succeed at the first API call.
UINT32 bufferLength = /* ... */;
LONG returnCode = ERROR_INSUFFICIENT_BUFFER;
while (returnCode == ERROR_INSUFFICIENT_BUFFER)
{
// Allocate buffer of specified length
buffer.reset( BYTE[bufferLength] );
//
// Or, in C++14, could use make_unique() instead, e.g.
//
// buffer = std::make_unique<BYTE[]>(bufferLength);
//
//
// Call some Win32 API.
//
// If the size of the buffer (stored in 'bufferLength') is not big enough,
// the API will return ERROR_INSUFFICIENT_BUFFER, and the required size
// in the [in, out] parameter 'bufferLength'.
// In that case, there will be another try in the next loop iteration
// (with the allocation of a bigger buffer).
//
// Else, we'll exit the while loop body, and there will be either a failure
// different from ERROR_INSUFFICIENT_BUFFER, or the call will be successful
// and the required information will be available in the buffer.
//
returnCode = ::SomeApiCall(inParam1, inParam2, inParam3,
&bufferLength, // size of output buffer
buffer.get(), // output buffer pointer
&outParam1, &outParam2);
}
if (Failed(returnCode))
{
// Handle failure, or throw exception, etc.
...
}
// All right!
// Do some processing with the returned information...
...
new[]
std::vector
たとえば、不注意なプログラマーが誤ってコピーを導入するのを防ぐために、の使用を禁止する一般的な規則があります。C++ コンテナーは、ポインターを使用したローリング ユア オウンよりも優先されるという一般的な規則があります。これは一般的な規則です。それには例外があります。まだまだあります。これらは単なる例です。
unique_ptr<char[]>
C のパフォーマンスと C++ の利便性が必要な場合に使用できます。数百万 (まだ信頼できない場合は数十億) の文字列を操作する必要があると考えてください。それらのそれぞれを個別のstring
またはvector<char>
オブジェクトに格納すると、メモリ (ヒープ) 管理ルーチンにとって大惨事になります。特に、異なる文字列を何度も割り当てて削除する必要がある場合。
ただし、その多くの文字列を格納するために単一のバッファーを割り当てることができます。char* buffer = (char*)malloc(total_size);
明らかな理由で気に入らない場合 (明らかでない場合は、「スマート ptrs を使用する理由」を検索してください)。あなたはむしろ好きですunique_ptr<char[]> buffer(new char[total_size]);
同様に、同じパフォーマンスと利便性に関する考慮事項が非char
データにも適用されます (数百万のベクトル/行列/オブジェクトを考慮してください)。