web-dev-qa-db-ja.com

どのシナリオで特定のSTLコンテナを使用しますか?

私はC++に関する私の本のSTLコンテナ、特にSTLとそのコンテナに関するセクションを読んでいます。今、私はそれらのそれぞれが固有の特性を持っていることを理解し、私はそれらのすべてを暗記することに近づいています...しかし、私がまだ把握していないのは、それらがそれぞれ使用されるシナリオです。

説明は何ですか?サンプルコードがより好まれます。

176
Daniel Sloof

このチートシート は、さまざまなコンテナのかなり良い要約を提供します。

さまざまな使用シナリオで使用するガイドとして、下部のフローチャートを参照してください。

http://linuxsoftware.co.nz/containerchoice.png

作成者 David Moore および licensed CC BY-SA 3.

318
zdan

これは、私が作成したDavid Mooreのバージョン(上記参照)に触発されたフローチャートです。これは、新しい標準(C++ 11)で(ほとんど)最新のものです。これは私の個人的な見解であり、議論の余地はありませんが、この議論にとって価値があると考えました。

enter image description here

177
Mikael Persson

簡単な答え:特に理由がない限り、すべてにstd::vectorを使用してください。

「ジー、std::vectorはXのためにここではうまく動作しない」と思っているケースを見つけたら、Xに基づいて進みます。

39
David Thornley

Scott MeyersによるEffective STLを見てください。 STLの使用方法の説明が得意です。

決められた/決められていない数のオブジェクトを保存したいが、決して削除したくない場合は、ベクターが必要です。これはC配列のデフォルトの置換であり、1つのように機能しますが、オーバーフローしません。 reserve()で事前にサイズを設定することもできます。

不明な数のオブジェクトを保存したいが、それらを追加して削除する場合、おそらくリストが必要です...ベクターとは異なり、次の要素を移動せずに要素を削除できるためです。ただし、ベクターよりも多くのメモリを必要とし、要素に順番にアクセスすることはできません。

要素の束を取得し、それらの要素の一意の値のみを検索する場合は、それらをすべてセットに読み込むと実行され、同様にそれらが並べ替えられます。

キーと値のペアが多数あり、それらをキーで並べ替えたい場合、マップは便利です...しかし、キーごとに1つの値しか保持しません。キーごとに複数の値が必要な場合は、マップ内の値としてベクトル/リストを使用するか、マルチマップを使用できます。

STLにはありませんが、STLのTR1アップデートには含まれています。キーごとにルックアップするキーと値のペアが多数あり、それらの順序を気にしない場合は、ハッシュを使用する-tr1 :: unordered_mapです。私はVisual C++ 7.1で使用しましたが、stdext :: hash_mapと呼ばれていました。マップのO(log n)のルックアップの代わりに、O(1)のルックアップがあります。

10
Mark Krenitsky

3つのプロパティを持つようにフローチャートを再設計しました。

  1. STLコンテナは2つの主要なクラスに分かれていると思います。基本的なコンテナとそれらは、基本的なコンテナを活用してポリシーを実装します。
  2. 最初に、フローチャートは、決定プロセスを、決定すべき主要な状況に分割し、各ケースについて詳しく説明する必要があります。
  3. 拡張コンテナの中には、内部コンテナとして異なる基本コンテナを選択する可能性があるものがあります。フローチャートでは、各基本コンテナを使用できる状況を考慮する必要があります。

フローチャート: enter image description here

詳細は このリンク で提供されています。

7
Ebrahim

これまで簡単に述べた重要なポイントは、連続したメモリ(C配列が与えるような)が必要な場合、vectorarray、またはstringのみを使用できることです。 。

コンパイル時にサイズがわかっている場合は、arrayを使用します。

汎用コンテナだけでなく、文字タイプのみを使用する必要があり、文字列が必要な場合は、stringを使用します。

その他の場合はすべてvectorを使用します(ほとんどの場合、vectorがコンテナのデフォルトの選択であるはずです)。

これらの3つすべてで、data()メンバー関数を使用して、コンテナーの最初の要素へのポインターを取得できます。

5
Jonathan Wakely

それはすべて、保存したいものと、コンテナで何をしたいかによって異なります。以下は、私が最もよく使用する傾向のあるコンテナークラスの(非常に網羅的ではない)例です。

vector:含まれるオブジェクトごとにメモリオーバーヘッドがほとんどまたはまったくないコンパクトなレイアウト。繰り返し処理するのに効率的です。追加、挿入、および消去は、特に複雑なオブジェクトの場合、高価になる可能性があります。含まれているオブジェクトをインデックスで簡単に見つけることができます。 myVector [10]。 Cで配列を使用する場所を使用します。多くの単純なオブジェクト(intなど)がある場所で使用します。コンテナに多くのオブジェクトを追加する前に、reserve()を使用することを忘れないでください。

list:含まれるオブジェクトごとの小さなメモリオーバーヘッド。繰り返し処理するのに効率的です。追加、挿入、消去は安価です。 Cでリンクリストを使用した場所を使用します。

set(およびmultiset):含まれるオブジェクトごとの重要なメモリオーバーヘッド。コンテナに特定のオブジェクトが含まれているかどうかをすばやく見つける必要がある場所を使用するか、コンテナを効率的にマージします。

map(およびmultimap):含まれるオブジェクトごとの重要なメモリオーバーヘッド。キーと値のペアを保存する場所を使用し、キーごとに値をすばやく検索します。

Zdanによって提案された cheat sheet のフローチャートは、より包括的なガイドを提供します。

3
Bids

私が学んだ1つの教訓は次のとおりです。コンテナの種類を1日に変更すると大きな驚きが生じる可能性があるため、クラスにラップしてみてください。

class CollectionOfFoo {
    Collection<Foo*> foos;
    .. delegate methods specifically 
}

それは前もってあまり費用がかからず、誰かがこの構造で操作xを行うたびにブレークしたいときのデバッグの時間を節約します。

ジョブに最適なデータ構造を選択することになります。

各データ構造はいくつかの操作を提供しますが、時間の複雑さはさまざまです。

O(1)、O(lg N)、O(N)など.

基本的に、どの操作が最も多く行われるのかを最もよく推測し、その操作をO(1)として持つデータ構造を使用する必要があります。

シンプルですよね(-:

2
vrdhn

Mikael Persson's 素晴らしいフローチャートを展開しました。いくつかのコンテナカテゴリ、アレイコンテナ、およびメモを追加しました。独自のコピーが必要な場合は、 here がGoogle図形描画です。基礎を作ってくれてありがとう、ミカエル! C++コンテナピッカー

1
John DiFini

私は、この質問の重複としてマークされている別の質問でこれに答えました。しかし、標準コンテナを選択する決定に関するいくつかの良い記事を参照するのは良いことだと思います。

@David Thornleyが答えたように、std :: vectorは、他に特別な必要がない場合の方法です。これは、C++の作成者であるBjarne Stroustrupによる2014年のブログでのアドバイスです。

こちらが記事へのリンクです https://isocpp.org/blog/2014/06/stroustrup-lists

それから引用して

そして、はい、私の推奨事項は、デフォルトでstd :: vectorを使用することです。

コメントでは、ユーザー@NathanOliverは別の優れたブログも提供しています。これには、より具体的な測定値があります。 https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html

1
CS Pei