2

ここで、オブジェクトのベクトルを初期化する 2 つの方法を比較します。

1.
    vector<Obj> someVector;
    Obj new_obj;
    someVector.push_back(new_obj);

2.
    vector<Obj*> ptrVector;
    Obj* objptr = new Obj();
    ptrVector.push_back(objptr);

最初の 1 つは、オブジェクトのポインターではなく、実際のオブジェクトを push_back します。ベクトル push_back はプッシュされる値をコピーしていますか? 私の問題は、巨大なオブジェクトと非常に長いベクトルがあるため、メモリを節約する最善の方法を見つける必要があることです。

  • 2番目の方法が良いですか?
  • 後で各オブジェクトを見つけ、同時に最小限のメモリを使用できるオブジェクト/ポインターのベクトルを取得する他の方法はありますか?
4

4 に答える 4

2

上記の 2 つのオプションのうち、含まれていないこの 3 番目のオプションが最も効率的です。

std::vector<Obj> someVector;
someVector.reserve(preCalculatedSize);
for (int i = 0; i < preCalculatedSize; ++i)
  someVector.emplace_back();

emplace_backオブジェクトを、 が配置するメモリに直接構築しますvector。利用前であればreserve、再配置や移動を避けることができます。

ただし、オブジェクトが本当に大きい場合は、キャッシュ コヒーレンシの利点は少なくなります。したがって、vectorスマート ポインターの a は理にかなっています。したがって、4 番目のオプション:

std::vector< std::unique_ptr<Obj> > someVector;
std::unique_ptr<Obj> element( new Obj );
someVector.push_back( std::move(element) );

おそらく最高です。ここでは、データの有効期間と、オーバーヘッドがほぼゼロの同じ構造でデータにアクセスする方法を表し、同期が取れなくなるのを防ぎます。

移動したいときは、明示的に移動する必要がありstd::moveます。std::unique_ptr何らかの理由で生のポインターが必要な場合は、.get()それにアクセスする方法です。 ->およびはすべてオーバーライドされるため、実際に呼び出す必要が*あるのは、.explicit operator bool.get()Obj*

これらのソリューションはどちらも C++11 を必要とします。C++11 がなく、オブジェクトが実際に大きい場合は、「データへのポインターのベクトル」が受け入れられます。

いずれにせよ、実際にすべきことは、モデルに最適なものを決定し、パフォーマンスをチェックして、実際にパフォーマンスの問題がある場合にのみ最適化を行うことです。

于 2013-09-25T03:12:39.153 に答える
1

Objクラスがポリモーフィックな動作を必要としない場合は、単純に型Objを直接vector<Obj>.

オブジェクトを に格納する場合はvector<Obj*>、それらのオブジェクトが不要になったときに手動で割り当てを解除する必要があります。この場合、vector<std::unique_ptr<Obj>>可能であれば使用することをお勧めしますが、ポリモーフィックな動作が必要な場合にのみ使用してください。

vector、オブジェクトをヒープに格納します (テンプレートでObjをオーバーライドしない限り、デフォルトで)。これらのオブジェクトは連続したメモリに格納されるため、ユースケースによっては、キャッシュの局所性も向上します。allocatorvector

を使用することの欠点vector<Obj>は、 への頻繁な挿入/削除により、オブジェクトvectorの再割り当てとコピーが発生する可能性があることです。Objただし、通常、これはアプリケーションのボトルネックにはなりません。そのように感じる場合は、プロファイルを作成する必要があります。

C++11の移動セマンティクスを使用すると、コピーの影響を大幅に減らすことができます。

于 2013-09-25T02:53:21.680 に答える
1

を使用するvector<Obj>と、事前にサイズを予約できれば、保存に必要なメモリが少なくなります。 ポインタのオーバーヘッドと動的メモリ割り当てのオーバーヘッドがあるため、ベクトルを再割り当てvector<Obj *>する必要がない場合よりも必然的に多くのメモリを使用します。vector<Obj>ただし、大きなオブジェクトが数個しかない場合は、このオーバーヘッドは比較的小さいかもしれません。

ただし、メモリが不足しvector<Obj>そうになっている場合、ベクトルを再割り当てするときに一時的に余分なストレージが必要になるため、事前に正しいサイズを予約できないと、 を使用すると問題が発生する可能性があります。

大きなオブジェクトの大きなベクトルがあると、メモリの断片化の問題が発生する可能性もあります。プログラムの実行の早い段階でベクトルを作成してサイズを予約できる場合、これは問題にならない可能性がありますが、後でベクトルを作成すると、ヒープのメモリ ホールが原因で問題が発生する可能性があります。

于 2013-09-25T02:57:16.333 に答える