286

std::unique_ptrたとえば、配列をサポートしています。

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

しかし、それは必要ですか?std::vectorおそらくorを使用する方が便利std::arrayです。

その構造の用途はありますか?

4

18 に答える 18

160

トレードオフがあり、必要なものに一致するソリューションを選択します。私の頭の上から:

初期サイズ

  • vectorunique_ptr<T[]>実行時にサイズを指定できるようにする
  • arrayサイズはコンパイル時にのみ指定できます

サイズ変更

  • arrayサイズ変更を許可しunique_ptr<T[]>ない
  • vectorする

保管所

  • vectorunique_ptr<T[]>オブジェクトの外部(通常はヒープ上)にデータを保存します
  • arrayデータをオブジェクトに直接保存します

コピー中

  • arrayvectorコピーを許可する
  • unique_ptr<T[]>コピーを許可しません

スワップ/移動

  • vectorunique_ptr<T[]>O(1) 回の操作とswap移動操作がある
  • arrayO(n) 回swapの移動操作があり、n は配列内の要素の数です。

ポインタ/参照/イテレータの無効化

  • arrayオブジェクトが生きている間、たとえswap()
  • unique_ptr<T[]>イテレータはありません。swap()ポインタと参照は、オブジェクトが生きている間だけ無効化されます。(スワップ後、ポインターはスワップした配列を指しているため、その意味ではまだ「有効」です。)
  • vector再割り当てのポインター、参照、および反復子を無効にする可能性があります (また、再割り当てが特定の操作でのみ発生する可能性があることを保証します)。

コンセプトとアルゴリズムとの互換性

  • array両方ともvectorコンテナです
  • unique_ptr<T[]>コンテナではありません

認めざるを得ませんが、これはポリシーベースの設計によるリファクタリングの機会のように見えます。

于 2013-05-29T02:40:58.230 に答える
88

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です。

于 2014-07-20T17:19:30.190 に答える
19

std::vectorおよび とは対照的にstd::arraystd::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());
}
于 2015-08-26T18:14:42.030 に答える
10

一部の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...
...
于 2014-08-25T19:52:54.140 に答える
3
  • バイナリ互換性の理由から、構造体にはポインターのみを含める必要があります。
  • で割り当てられたメモリを返す API とのインターフェイスが必要ですnew[]
  • あなたの会社またはプロジェクトには、std::vectorたとえば、不注意なプログラマーが誤ってコピーを導入するのを防ぐために、の使用を禁止する一般的な規則があります。
  • この場合、不注意なプログラマーが誤ってコピーを導入するのを防ぎたいと考えています。

C++ コンテナーは、ポインターを使用したローリング ユア オウンよりも優先されるという一般的な規則があります。これは一般的な規則です。それには例外があります。まだまだあります。これらは単なる例です。

于 2014-08-28T16:30:05.733 に答える
2

unique_ptr<char[]>C のパフォーマンスと C++ の利便性が必要な場合に使用できます。数百万 (まだ信頼できない場合は数十億) の文字列を操作する必要があると考えてください。それらのそれぞれを個別のstringまたはvector<char>オブジェクトに格納すると、メモリ (ヒープ) 管理ルーチンにとって大惨事になります。特に、異なる文字列を何度も割り当てて削除する必要がある場合。

ただし、その多くの文字列を格納するために単一のバッファーを割り当てることができます。char* buffer = (char*)malloc(total_size);明らかな理由で気に入らない場合 (明らかでない場合は、「スマート ptrs を使用する理由」を検索してください)。あなたはむしろ好きですunique_ptr<char[]> buffer(new char[total_size]);

同様に、同じパフォーマンスと利便性に関する考慮事項が非charデータにも適用されます (数百万のベクトル/行列/オブジェクトを考慮してください)。

于 2016-08-18T10:52:19.317 に答える