2016-07-31 11 views
0

std :: vectorは連続して割り当てられたメモリ(キャッシュに優しい)が保証されているため、std :: vectorは良いと聞きました。それでは、このようなシーケンシャルな「新しい」演算子はどうでしょうか?シーケンシャルな 'new'演算子は連続したメモリを割り当てますか?

{ 
    new Test1(); 
    new Test2(); 
    new Test3(); 
} 

ヒープ上に連続して割り当てられたメモリを作成しませんか?

答えて

3

シーケンシャルnew式は必ずしもシーケンシャルなメモリブロックを割り当てるわけではありません。

しかし、C++ 14では、特定の条件下では、1つのnew式(必然的に充分に大きな連続したチャンクを割り当てます)で置き換えることができるnew式のシーケンスを特別にサポートしています。 delete式は1つのdelete式で置き換えられます。

C++ 14(N3936ドラフト)§5.3.4/ 10:

実装は、交換可能なグローバル割り当て関数(18.6.1.1、18.6.1.2への呼び出しを省略させます)。そうであれば、記憶装置は代わりに実装によって提供されるか、別のnewの表現を拡張することによって提供される。 e1の評価はe2の評価の前に配列決定され、そして
から
:実装は延長されない割り当てた以下が真であるかどうnew -expression e2用のストレージを提供するnew -expression e1の割り当てを延長することができます - e2e1ストレージを取得するたびに評価され、
- 両方e1e2が同じ交換可能なグローバル割り当て関数を呼び出し、そして
- e1e2によって呼び出さ割り当て機能を投げている場合、任意exceptio e1又はe2いずれかの評価にスローNS最初同じハンドラに巻き込まれるであろう、そして
- e1e2によって生成されるポインタ値を評価delete -expressionsにオペランドであり、
- e2の評価は前に配列決定されますオペランドがe1によって生成されたポインタ値であるdelete-expressionの評価。

0

メモリ管理は、実際のオペレーティングシステム次第です - 実行時に、これは(おそらくかかわらず)の行の数回は、すなわち連続割り当てが保証されていないC malloc機能を呼び出すことと同じです。オブジェクトが連続的なメモリブロックに格納されることを保証するために、オブジェクトは配列に保持されるべきです。

私はどのアプリケーションを使用しているのかよくわかりませんが、ほとんどの場合、キャッシュの使いやすさからのスピードアップは、オブジェクトを渡すオーバーヘッドによってはるかに大きくなります。キャッシュの利便性は、CPUがアレイを急速にキャッシュ内外にシャッフルする必要がないため、大きなデータベース(例えば、長いアレイのmergesort)上で動作しているプログラムの速度を向上させるだけですが、オブジェクトの数が少ない場合は、その効果は非常に小さいため、キャッシュについて心配する必要があります。配列内のブロックとしてではなく、個々のベクトルを個別に宣言している場合は、配列の中にそれらを配置する必要はないので、プログラムを高速化することはできません。

0

ほとんどの実装では、アロケータは以前は空きメモリを保持していたため、常に連続したメモリを取得するとは思われませんでした。

このケースについて考えてみましょう:Test1は大きいオブジェクトです、Test2は小さいものです、Test3はミッドサイズです。

Test1に割り当てると、現在のメモリプールには再利用可能なメモリが十分にないため、ヒープを拡張して割り当てを要求します。 次に、小さいTest2のために、これは以前のfree'dからの再利用可能なメモリがあるという小さなオブジェクトなので、そのプールからTest2を取得します。

Test2に対するその類似 Test3について

が、パフォーマンスのためにアロケータは、異なるサイズ範囲のための複数のプールを保持することになるので、Test3Test2後に行かなくてもよいです。

注:これらはすべて仕様書からは必須ではなく、実装次第です。ここで示唆されているのは、通常の実装(バディメモリ割り当て)です。

関連する問題