2012-08-03 10 views
17

タイプTの場合、タイプstd::list<T>は同じ一定のサイズを持つと仮定できますか?ちょうどそれを明確にするために、私は、それによって割り当てられたメモリではなく、「メイン」タイプそのもののサイズだけを意味します。sizeof(std :: list <T>)は、Tの種類によって異なりますか?

T自体のサイズは、アロケータを使用して割り当てられたリストノードのサイズに影響を与えるだけであると私は考えています。

はしかし、私は考えることができるsizeof(std::list<T>)のvariancyを引き起こすかもしれない二つのものがあります:

  1. 「最適化」std::list<T>自体にTインスタンスのいくつかを置くことによってstd::list型にしようと、標準C++ライブラリ。それは私にとっては悪い考えであり、おそらく標準によって定められた「一定の時間」の要件を破るでしょう。
  2. ライブラリの特殊化がstd::list<T>の標準C++で、一部のタイプでは特殊化のサイズが異なります。

(1)または(2)の用途は考えられませんが、間違っている可能性があります。

私が達成しようとしているのは、std::list<T>を使ってテンプレートクラスに固定サイズのスライスアロケータを使用することです。注意点としては


:これはTの異なる種類の分散程度であり、異なるアロケータのためのない。すべてのインスタンス化を明示的に制御し、すべてはstd::allocatorを使用します。

+0

興味深い+1。私はかなり確信しています、標準は同じサイズを保証するものではありませんが、まだ+1とただのコメント:) –

+0

私は 'list'ではなく' vector'について考えていましたが、 'T *'すべてのポインタが同じサイズではありません...どうしてメンバー関数のコンテナをどのように作成したのかよく分かりませんが... – BoBTFish

+0

@BoBTFish - すべてのポインタは同じサイズです。 –

答えて

8

はいです。

list<T>オブジェクトのサイズに関する規格は、私が知る限り正確なものではありません。それでも、他にも保証があります。


私たちはいくつかのことを暴くてみましょう:

標準C++ライブラリは、「最適化」にstd::listタイプをしようとstd::list<T>自体にTインスタンスのいくつかを置くことによって。それは私にとっては悪い考えであり、おそらく標準によって定められた「一定の時間」の要件を破るでしょう。

O(5)がO(1)であるため、この数が限定されている限り、「一定時間」の要件を壊さない。しかし、spliceの操作の間に、ノードはあるリストから別のリストに移動する必要があります。に移動することなく、。したがって、ローカルストレージは禁止されています。

ライブラリの特殊化がstd::list<T>の標準C++で、種類が異なり、特殊化のサイズが異なります。

すでにローカルストレージの可能性を排除するので、それ自体によってベースstd::list<T>タイプの他の変形を想像することは困難です。


そして、私たちはどのような事項を心配してみましょう:アロケータ:

std::list<T>によって割り当てられたメモリは、その2番目のテンプレート引数によって提供されます。ほとんどのアロケータ(を含む)は単純なポインタ型を使用します:T* ...しかし、アロケータはこの型を自由に変更する必要があります。

したがって、allocatorパラメータ(より正確にはポインタ型)を変更することで、私が見たすべての実装でstd::listコンテナのサイズが自然に変更されます。

アロケータ自体はいくつかのタイプに特化することができますが、リバインドマジックでは達成するのが少し難しいことに注意してください。

+0

+1は、アロケータがフットプリントにどのように影響を与えるかを具体的に考えるためのものです。非常に素晴らしい。 – Jon

4

C++ 11標準(コンテナ)の第23章では、サイズについて何も言わないので、技術的にはサイズが一定であるとは仮定できません。実装者は、(理論的には)そのフットプリントに影響を与える方法で特定のプリミティブのコンテナを特化することができます。

実際には、sizeof(list<T>) == sizeof(list<int>)という静的アサーションを使用し、sizeof(list<int>)を「固定」サイズとして使用できます。最悪の事態は、コンパイル時のエラーです。

0

std::list<T>を使用するクラスの固定サイズスライスアロケータは、リスト自体に固定サイズのスライスアロケータを使用しない限り、リストヘッダのリスト項目よりも多くの割り当てが存在する可能性があります。

これで、2番目のテンプレート引数であるアロケータを使用して、独自の固定サイズスライスアロケータをリストに追加できます。しかし、ねじれがある:あなたはスライスがどれほど大きくなければならないか分からない。 list<T>allocator<T>を受け取りますが、本当に必要なのはallocator<U>です。ここで、Uはprev/nextポインタとTを含む構造体です。これを得るには、メソッドrebindを呼び出し、それにはtemplate <typename T> template <typename T> allocator<U> allocator<T>::rebind<U>()というシグネチャがあります。

私は実際にこれを行う必要があったので、いくつかのスライスサイズのアロケータのコレクションを保持するオブジェクトを作成することでした。アロケータ自体はこれへの共有ポインタとそのアロケータのサイズのためのアロケータへの共有ポインタを保持していました。リバインドでは、コレクションから適切なアロケータを取り出したか、存在しない場合はアロケータを作成しました。これを行うと、副作用としてリストの割り当てが解決されます。これは、複数のサイズが存在する場合、それぞれに個別のプールが作成されるためです。多くの異なるサイズがあるようなものではありません。なぜなら、オブジェクトは大きくないからです。

+0

リストはスライスアロケータ自体の内部で使用されるため、直接割り付ける必要があります。しかし、 'std :: list '自体は、スライスアロケータを使用することで恩恵を受けるほど小さくなければなりません。 –

関連する問題