2013-03-18 10 views
15

でカスタムSTLアロケータで、私は、カスタムアロケータを構築するつもりだいくつかのクラスTN要素を格納するための大きなブロック(配列)を事前割り当て、その後、ちょうど内側率を高めますアレイからサービスへの割り当て要求。再結合が事前に割り当てられたブロック

私が事前に割り当てられたブロック内の要素の任意の初期化を望んでいんので、このような何かが動作しません。

T buffer[N]; 

をため、この場合には、Tのコンストラクタが呼び出されますブロックの要素のNの場合

私の理解がstd::aligned_storageTのコンストラクタを呼び出していないということですので、私は、std::aligned_storageを使用してのこのような何か考えた:

std::aligned_storage< 
    N * sizeof(T), 
    std::alignment_of<T>::value 
>::type buffer; 

T* base = static_cast<T*>(static_cast<void*>(&buffer)); 

のときのために割り当て、その後アロケータはちょうどベースポインタをインクリメントすることができますTが((base+N)まで)要求され、Tは、必要に応じて(配置)の場所にを構築することができる。

このスキームを使用して、STLコンテナカスタムアロケータを定義します。しかし、rebindingの場合はここに問題があるようです。実際、私の理解が正しいならば、STLアロケータはタイプTからタイプUへのリバインドをサポートすべきです。 std::list<T>std::map状または他のノードベースのコンテナ)のようなコンテナは、実際にタイプTのないノードを割り当てるアロケータを使用するが、異なるタイプUの(Tおよびノー​​ドの他の「ヘッダ」オーバーヘッド情報を含む)からです。 上記のstd::aligned_storageアプローチはリバインドでうまくいくでしょうか?または、(私が思う)Tの正しい位置合わせはではありません。は、別の異なるタイプの正しい位置合わせを暗示します。U

この問題を解決するにはどうすればよいですか?

前述のbufferを定義して、別の種類のリバウンドにも対応できるようにするにはどうすればよいですか?U

この問題は別の観点から攻撃されるべきですか?もしそうなら、何?

+0

代わりに、 'std :: alignment_of :: value'を代わりに使って、C++標準アロケータでサポートされている型に対して正しく整列させることはできませんか?もちろん、特別な(より厳密な)アラインメント要件(最良の例SSE)を持つ型では機能しませんが、標準アロケータであっても、これらは常に問題になります。 –

答えて

10

あなたは正しい方向にあります。

アロケータのコピーは、均等で、変換(リバウンド)したコピーを比較する必要があります。 equalを比較すると、互いのポインタの割り当てを解除できます。したがって、std::list<int>などのコンテナは、your_alloc<int>your_alloc<node<int>>に再バインドし、your_alloc<int>を使用してyour_alloc<node<int>>を構築します。そして技術的にはyour_alloc<node<int>>your_alloc<int>によって割り当てられたポインタの割り当てを解除する必要があります。

Hereは、この要件を満たすための私の試みです。このコードを自由にコピー/修正/乱用してください。私の意向は、教育することであり、世界のアロケータ・サプライヤにはなりません(これは、とにかく有利なものではありません:-))。

この例では、アライメントのやり方が少し異なります。興味のあるプラットフォーム(OS X、iOS)でmallocが16バイトのアライメントされたメモリを返すことがわかったので、すべてカスタムアロケータが返す必要があります。その番号をシステムに適したものに変更することができます。

このアライメントのハードワイヤリングは、1つのプールがすべて16バイトで整列されているので、安全に複数のallocator<int>allocator<node<int>>を供給できることを意味します(これで十分です)。また、コピーがすべて同じバッファを共有しているため、コピーが変換されたコピーであっても、ポインタがバッファを指しているときを検出できることも意味します。

C++委員会は、アロケータが参照型であることを効果的に指定しています。コピーは同等で、同じメモリプールを指しています。

アロケータに実際に埋め込まれたメモリプールを使用して不正行為を解消することはできますが、一部の実装では一部のコンテナしか使用できず、標準から引用して戻すことはできません。

+0

サンプルアロケータコードをご提供いただき、ありがとうございます。 –

+1

もし 'stack_allocator'から64バイトアライメント(キャッシュアライメントのためなど)が必要な場合は、グローバルな' :: operator new'を再定義して同じ64バイトアライメントを提供する必要がありますか? – TemplateRex

+1

@rhalbersmaすることもできますし、 ':: operator new'から常に' 64-alignof(std :: max_align_t) 'を要求し、64バイト境界でのみ使用することもできます何らかの理由で元のアラインされていないポインタを ':: operator delete'に戻す必要があります) –

関連する問題