まず、 astd::vector<std::vector<int>>
はさまざまなサイズの内部ベクトルを持つことができます。ただし、この型を使用して 2D 配列を模倣することについて具体的に話していると仮定します。ベクターを作成するときにベクターのサイズを設定すると仮定すると、すべてが一度に行われるため、動的割り当ての量について心配する必要はおそらくありません。
ベクトルは、その要素の配列を内部的に割り当てます。したがって、外側のベクトルはベクトルの配列を割り当てており、それらの内側のベクトルのそれぞれはint
s の配列を割り当てています。次のように考えることができます。
┌─────┐
│ vec │
└──╂──┘
┃
▼
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ vec │ vec │ vec │ vec │ vec │ vec │ vec │ vec │ vec │
└──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┘
┃ ┗━━━━━━━━━━┓
▼ ▼
┌─────┬─────┬┄ ┌─────┬─────┬┄
│ int │ int │ │ int │ int │
└─────┴─────┴┄ └─────┴─────┴┄
ご覧のとおり、 int
s の配列は互いに完全に分離されています。それらはメモリの完全に異なる場所にある可能性があります。これは断片化として知られています。ほとんどの場合、メモリの単一の連続したブロックにはなりません。このため、2D ベクターの異なる「行」にまたがる要素にアクセスすると、キャッシュ ミスが発生する可能性があります。
ただし、int
s の 1 つのベクトルを割り当てて独自の 2 次元インデックスを作成すると、メモリ レイアウトは次のようになります。
┌─────┐
│ vec │
└──╂──┘
┃
▼
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬┄
│ int │ int │ int │ int │ int │ int │ int │ int │ int │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴┄
はint
、単一の連続したメモリ ブロックに格納されます。どのアクセスも同様のメモリ アドレスを持ち、キャッシュ ヒットにつながる可能性があります。これにより、パフォーマンスが向上する可能性があります。