std :: vectorは連続して割り当てられたメモリ(キャッシュに優しい)が保証されているため、std :: vectorは良いと聞きました。それでは、このようなシーケンシャルな「新しい」演算子はどうでしょうか?シーケンシャルな 'new'演算子は連続したメモリを割り当てますか?
{
new Test1();
new Test2();
new Test3();
}
ヒープ上に連続して割り当てられたメモリを作成しませんか?
std :: vectorは連続して割り当てられたメモリ(キャッシュに優しい)が保証されているため、std :: vectorは良いと聞きました。それでは、このようなシーケンシャルな「新しい」演算子はどうでしょうか?シーケンシャルな 'new'演算子は連続したメモリを割り当てますか?
{
new Test1();
new Test2();
new Test3();
}
ヒープ上に連続して割り当てられたメモリを作成しませんか?
シーケンシャルnew
式は必ずしもシーケンシャルなメモリブロックを割り当てるわけではありません。
しかし、C++ 14では、特定の条件下では、1つのnew
式(必然的に充分に大きな連続したチャンクを割り当てます)で置き換えることができるnew
式のシーケンスを特別にサポートしています。 delete
式は1つのdelete
式で置き換えられます。
”実装は、交換可能なグローバル割り当て関数(18.6.1.1、18.6.1.2への呼び出しを省略させます)。そうであれば、記憶装置は代わりに実装によって提供されるか、別の
new
の表現を拡張することによって提供される。e1
の評価はe2
の評価の前に配列決定され、そして
から
:実装は延長されない割り当てた以下が真であるかどうnew
-expressione2
用のストレージを提供するnew
-expressione1
の割り当てを延長することができます -e2
e1
ストレージを取得するたびに評価され、
- 両方e1
とe2
が同じ交換可能なグローバル割り当て関数を呼び出し、そして
-e1
とe2
によって呼び出さ割り当て機能を投げている場合、任意exceptioe1
又はe2
いずれかの評価にスローNS最初同じハンドラに巻き込まれるであろう、そして
-e1
とe2
によって生成されるポインタ値を評価delete
-expressionsにオペランドであり、
-e2
の評価は前に配列決定されますオペランドがe1
によって生成されたポインタ値であるdelete
-expressionの評価。
メモリ管理は、実際のオペレーティングシステム次第です - 実行時に、これは(おそらくかかわらず)の行の数回は、すなわち連続割り当てが保証されていないC malloc
機能を呼び出すことと同じです。オブジェクトが連続的なメモリブロックに格納されることを保証するために、オブジェクトは配列に保持されるべきです。
私はどのアプリケーションを使用しているのかよくわかりませんが、ほとんどの場合、キャッシュの使いやすさからのスピードアップは、オブジェクトを渡すオーバーヘッドによってはるかに大きくなります。キャッシュの利便性は、CPUがアレイを急速にキャッシュ内外にシャッフルする必要がないため、大きなデータベース(例えば、長いアレイのmergesort)上で動作しているプログラムの速度を向上させるだけですが、オブジェクトの数が少ない場合は、その効果は非常に小さいため、キャッシュについて心配する必要があります。配列内のブロックとしてではなく、個々のベクトルを個別に宣言している場合は、配列の中にそれらを配置する必要はないので、プログラムを高速化することはできません。
ほとんどの実装では、アロケータは以前は空きメモリを保持していたため、常に連続したメモリを取得するとは思われませんでした。
このケースについて考えてみましょう:Test1
は大きいオブジェクトです、Test2
は小さいものです、Test3
はミッドサイズです。
Test1
に割り当てると、現在のメモリプールには再利用可能なメモリが十分にないため、ヒープを拡張して割り当てを要求します。 次に、小さいTest2
のために、これは以前のfree'dからの再利用可能なメモリがあるという小さなオブジェクトなので、そのプールからTest2
を取得します。
Test2
に対するその類似
Test3
について
が、パフォーマンスのためにアロケータは、異なるサイズ範囲のための複数のプールを保持することになるので、Test3
はTest2
後に行かなくてもよいです。
注:これらはすべて仕様書からは必須ではなく、実装次第です。ここで示唆されているのは、通常の実装(バディメモリ割り当て)です。