C ++でのstd::vector
との違いは何std::array
ですか?いつ他の人よりも好まれるべきですか?それぞれの長所と短所は何ですか?私の教科書がしていることは、それらがどのように同じであるかをリストすることだけです。
std::array
はC ++配列と同じではありません。std::array
クラスのユーザーからポインターを隠すことを主な目的とする、C ++配列の非常に薄いラッパーです。回答を更新します。
C ++でのstd::vector
との違いは何std::array
ですか?いつ他の人よりも好まれるべきですか?それぞれの長所と短所は何ですか?私の教科書がしていることは、それらがどのように同じであるかをリストすることだけです。
std::array
はC ++配列と同じではありません。std::array
クラスのユーザーからポインターを隠すことを主な目的とする、C ++配列の非常に薄いラッパーです。回答を更新します。
回答:
std::vector
動的配列1をカプセル化するテンプレートクラスです。ヒープに格納され、要素が追加または削除されると自動的に拡大および縮小します。これは、すべてのフック(提供begin()
、end()
それはSTLの残りの部分と罰金を動作させる、イテレータ、など)。また、ベクトルの中央に要素を挿入するなど、通常の配列では扱いにくい操作を実行できるいくつかの便利なメソッドもあります(これは、背後にある次の要素を移動するすべての作業を処理します)。
ヒープに割り当てられたメモリに要素を格納するため、静的配列に関してオーバーヘッドが発生します。
std::array
静的サイズの配列をカプセル化するテンプレートクラスであり、オブジェクト自体の内部に格納されます。つまり、スタックでクラスをインスタンス化すると、配列自体がスタックに配置されます。そのサイズはコンパイル時に既知である必要があり(テンプレートパラメーターとして渡されます)、拡大または縮小できません。
はより制限されていますがstd::vector
、実際にはほとんどがCスタイルの配列の軽量ラッパーであるため、特に小さいサイズの場合は、多くの場合より効率的です。ただし、ポインターへの暗黙の変換が無効になっているため、より安全であり、std::vector
STLアルゴリズムおよびその他のコンテナーでSTL関連の機能の多くを提供するため、STLアルゴリズムおよびcoで簡単に使用できます。とにかく、固定サイズの非常に制限があるため、ほど柔軟ではありませんstd::vector
。
概要についてはstd::array
、見ていこの記事を。std::vector
可能な操作の簡単な紹介については、そのドキュメントをご覧ください。
static
C ++でのキーワードは、3つの異なる無関係な意味を持っており、この用語はまた、コンパイル時に固定されているものについての話に頻繁に使用されています。「静的サイズ」がもう少し明確であることを願っています。
std::vector<T>
クラスの使用:
... 組み込み配列を使用して実行できること(既存の要素の読み取りと書き込み)のみを実行している場合、組み込み配列を使用するのと同じくらい高速です。
...新しい要素が挿入されると自動的にサイズ変更されます。
... ベクトルの最初または途中に新しい要素を挿入して、残りの要素を自動的に「上」にシフトすることができます(意味がありますか?)。また、内の任意の場所にある要素を削除してstd::vector
、残りの要素を自動的に下に移動することもできます。
...メソッドを使用して範囲チェック済みの読み取りを実行できますat()
([]
このチェックを実行したくない場合は、常にインデクサーを使用できます)。
使用には2つの 3つの主な注意事項がありますstd::vector<T>
。
基になるポインターへの信頼できるアクセスがありません。配列のアドレスを要求するサードパーティの関数を処理している場合は、問題になる可能性があります。
std::vector<bool>
クラスは愚かです。配列ではなく、圧縮されたビットフィールドとして実装されます。bool
sの配列が必要な場合は避けてください。
使用中、std::vector<T>
sは同じ数の要素を持つC ++配列よりも少し大きくなります。これは、現在のサイズなど、他の少量の情報を追跡する必要があるためstd::vector<T>
です。また、sのサイズを変更するたびに、必要以上のスペースを確保するためです。これは、新しい要素が挿入されるたびにサイズを変更する必要がないようにするためです。この動作はカスタムを提供することで変更できますが、allocator
その必要性を感じたことは一度もありません!
編集:質問に対するZudの回答を読んだ後、これを追加する必要があると感じました:
std::array<T>
クラスは、C ++の配列と同じではありません。std::array<T>
は、C ++配列の非常に薄いラッパーであり、クラスのユーザーからポインターを隠すことを主な目的としています(C ++では、配列は暗黙的にポインターとして暗黙的にキャストされ、多くの場合、期待を裏切る結果になります)。std::array<T>
クラスはまた、その大きさ(長さ)は、非常に有用であり得る記憶します。
data()
、a std::vector<T>
を呼び出して、基になるポインターを取得できます。要素0のアドレスを取得することもできます(C ++ 11での動作が保証されていますが、おそらく以前のバージョンでも動作します)。
@MatteoItaliaによって指摘された点を強調するために、効率の違いはデータが格納される場所です。ヒープメモリ(で必要vector
)は、システムにメモリを割り当てるための呼び出しを必要とします。これは、サイクルをカウントしている場合にはコストがかかる可能性があります。スタックメモリ(の可能性がありますarray
)は、メモリがスタックポインタを調整するだけで割り当てられ、関数へのエントリ時に1回だけ実行されるため、実質的に時間の観点から「ゼロオーバーヘッド」です。スタックは、メモリの断片化も回避します。確かに、std::array
常にスタックにあるとは限りません。割り当てる場所によって異なりますが、ヒープとのメモリ割り当ては、ベクターに比べて1つ少なくなります。あなたが持っている場合
間違いなくstd::array
ベクトルを使用します。これらの要件のいずれかが真でない場合は、を使用しstd::vector
ます。
new std::array
か、 'new`を使用して割り当てるクラスのメンバーにします。
new std::array
、コンパイル時にそのサイズを知っていることを期待しており、サイズを変更することはできませんが、ヒープ上に残っているということですか?
new std::array
vs を使用しても大きなメリットはありませんnew std::vector
。
多次元配列の使用を検討している場合は、std :: arrayとstd :: vectorの間に1つの追加の違いがあります。多次元std :: arrayは、cスタイルの配列と同じように、すべての次元で要素をメモリにパックします。多次元std :: vectorは、すべての次元でパックされるわけではありません。
次の宣言があるとします。
int cConc[3][5];
std::array<std::array<int, 5>, 3> aConc;
int **ptrConc; // initialized to [3][5] via new and destructed via delete
std::vector<std::vector<int>> vConc; // initialized to [3][5]
cスタイルの配列(cConc)またはstd :: array(aConc)の最初の要素へのポインターは、先行する各要素に1を追加することにより、配列全体を反復できます。彼らはしっかりと詰め込まれています。
ベクトル配列(vConc)の最初の要素へのポインターまたはポインター配列(ptrConc)は、最初の5つの要素(この場合)を介してのみ反復可能であり、(システムでは)12バイトのオーバーヘッドがあります。次のベクトル。
つまり、[3] [1000]配列として初期化されたstd :: vector>配列は、[1000] [3]配列として初期化された配列よりもメモリ内ではるかに小さくなり、両方ともstdよりもメモリ内で大きくなります。いずれかの方法で割り当てられた配列。
これは、メモリのオーバーヘッドを考慮せずに単純に多次元ベクトル(またはポインター)配列をopenGLに渡すことはできないが、単純に多次元std :: arrayをopenGLに渡して機能させることもできることを意味します。
ベクトルはコンテナークラスであり、配列は割り当てられたメモリです。
std::vector<T>
対に対処しているようですT[]
が、問題はstd::vector<T>
対についてstd::array<T>
です。
std::vector
対std::array
とどのように用語が異なっています。