連想コンテナの概要
シーケンシャル コンテナはすべての C++ 基本データ型を格納しますが、連想コンテナはまったく異なります。要素の値を格納している間、このタイプのコンテナは追加の値 (各要素の「キー」とも呼ばれます。その本質も C++ 基本データ型です) を提供します。またはカスタム タイプの要素)、その機能は、連想コンテナを使用するプロセスで、ターゲット要素のキーの値がわかっている場合、ターゲット要素をキーを渡すことなく直接見つけることができることです。コンテナ全体を走査する方法。
順次コンテナーを放棄し、連想コンテナーを使用して要素を格納することは、多くの場合、連想コンテナーが保管されている要素を迅速に検索、読み取り、または削除できるためであり、このタイプのコンテナーは順次コンテナーよりも効率的に要素を挿入するためです。
つまり、連想コンテナに格納される要素はすべて「キーと値のペア」( <key,value> ) であり、これが順次コンテナとの最大の違いです。また、順次コンテナに格納されている要素はデフォルトではソートされませんが、連想コンテナに格納されている要素はデフォルトで各要素のキー値のサイズに応じて昇順にソートされます。
連想コンテナのこれらの特性は、STL 標準ライブラリがこのタイプのコンテナを実装するときに、最下層が「赤黒ツリー」データ構造を使用して各キーと値のペアを編成して格納するという事実に起因しています。
関連コンテナタイプ
C++ STL 標準ライブラリには、map、set、multimap、multiset の 4 種類の連想コンテナが用意されており、それぞれの特性を次の表に示します。
連想コンテナ名 | 特徴 |
---|---|
地図 | <map> ヘッダー ファイルで定義され、このコンテナに格納されるデータの各要素のキーは一意である必要があり (つまり、繰り返してはいけない)、コンテナはデフォルトで各要素のサイズに従って昇順に並べ替えられます。要素キー (std::less<T> を呼び出します)。 |
セット | <set> ヘッダー ファイルで定義され、このコンテナに格納されているデータを使用して、各要素のキーと値はまったく同じであり、各要素の値を繰り返すことはできません (各要素のキーの一意性が保証されています)。コンテナーは、各要素のキー (実際には要素の値) のサイズに従って昇順に自動的に並べ替えられます (std::less<T> を呼び出します)。 |
マルチマップ | <map> ヘッダー ファイルで定義され、マップ コンテナーとの唯一の違いは、マルチマップ コンテナーに格納されている要素のキーを繰り返すことができることです。 |
マルチセット | <set> ヘッダー ファイルで定義され、set コンテナーとの唯一の違いは、マルチセット コンテナーに格納されている要素の値を繰り返すことができることです (値が繰り返されると、キーも繰り返されることになります)。 |
さらに、C++ 11 では 4 つの新しいハッシュ コンテナー、つまり unowned_map、unowned_multimap および unowned_set、unowned_multiset が追加されました。厳密に言えば、これらも連想コンテナですが、基礎となるハッシュ コンテナは赤黒ツリーの代わりにハッシュ テーブルを使用します。
ペアの詳しい使い方
連想コンテナーは、次のような「キーと値のペア」の形式でデータを保存することがわかっています。
<"C语言教程", "http://c.biancheng.net/c/">
<"Python教程", "http://c.biancheng.net/python/">
<"Java教程", "http://c.biancheng.net/java/">
上に示したように、各行はキーと値のペアを表し、最初の要素がキー (キー) として機能し、2 番目の要素が値 (値) として機能します。
各連想コンテナに格納されるデータの特性に基づいて、セットおよびマルチセットの連想コンテナ ストレージは、各キーと値のペアのキーと値がすべて対応して等しい場合にのみ使用できます。それ以外の場合は、マップまたはマルチマップ連想コンテナを使用する必要があることに注意してください。使用済み。
「キーと値のペア」が通常のデータ型ではないことを考慮して、C++ STL 標準ライブラリはペア クラス テンプレートを提供します。これは、2 つの通常の要素 (C++ の基本データ型、構造体、およびクラス定義型) が新しい要素 <first, Second> として作成されます。要素の形式から、ペア クラス テンプレートを使用して「キーと値のペア」の形式で要素を作成することが完璧であることがわかります。
ペア クラス テンプレートは <utility> ヘッダー ファイルで定義されているため、このクラス テンプレートを使用する前にこのヘッダー ファイルをインポートする必要があることに注意してください。
- C++11 標準より前は、次の 3 つのコンストラクターがペア クラス テンプレートで提供されていました。
// 1) 默认构造函数,即创建空的 pair 对象
pair();
// 2) 直接使用 2 个元素初始化成 pair 对象
pair (const first_type& a, const second_type& b);
// 3) 拷贝(复制)构造函数,即借助另一个 pair 对象,创建新的 pair 对象
template<class U, class V> pair (const pair<U,V>& pr);
C++11 標準では、右辺値参照の導入に基づいて、次の 2 つのコンストラクターがペア クラス テンプレートに追加されます。
// 4) 移动构造函数
template<class U, class V> pair (pair<U,V>&& pr);
// 5) 使用右值引用参数,创建 pair 对象
template<class U, class V> pair (U&& a, V&& b);
さらに、C++11 標準のペア クラス テンプレートでは、次のコンストラクターも追加されます。pair (piecewise_construct_t pwc, tuple<Args1...> first_args, tuple<Args2...> second_args);
ただし、ペア クラス テンプレートを構築するこの方法はほとんど使用されません。
次のプログラムは、ペア オブジェクトを作成する上記の方法を示しています。
#include <iostream>
#include <utility> // pair
#include <string> // string
using namespace std;
int main() {
// 调用构造函数 1,也就是默认构造函数
pair <string, double> pair1;
// 调用第 2 种构造函数
pair <string, string> pair2("STL教程","http://c.biancheng.net/stl/");
// 调用拷贝构造函数
pair <string, string> pair3(pair2);
// 调用移动构造函数
pair <string, string> pair4(make_pair("C++教程", "http://c.biancheng.net/cplus/"));
// 调用第 5 种构造函数
pair <string, string> pair5(string("Python教程"), string("http://c.biancheng.net/python/"));
cout << "pair1: " << pair1.first << " " << pair1.second << endl;
cout << "pair2: "<< pair2.first << " " << pair2.second << endl;
cout << "pair3: " << pair3.first << " " << pair3.second << endl;
cout << "pair4: " << pair4.first << " " << pair4.second << endl;
cout << "pair5: " << pair5.first << " " << pair5.second << endl;
return 0;
}
プログラムの出力は次のとおりです。
pair1: 0
pair2: STL教程 http://c.biancheng.net/stl/
pair3: STL教程 http://c.biancheng.net/stl/
pair4: C++教程 http://c.biancheng.net/cplus/
pair5: Python教程 http://c.biancheng.net/python/
上記のプログラムは、pair4 オブジェクトを作成するときに、<utility> ヘッダー ファイルによって提供される make_pair() 関数を呼び出します。その機能は、ペア オブジェクトを生成することです。したがって、make_pair() 関数の戻り値 (一時オブジェクト) をパラメーターとして parse() コンストラクターに渡すと、コピー コンストラクターの代わりに移動コンストラクターが呼び出されます。
上記のプログラムに基づいて、C++ 11 では、次のように、pair1 オブジェクトに値を手動で割り当てることもできます。
pair1.first = "Java教程";
pair1.second = "http://c.biancheng.net/java/";
cout << "new pair1: " << pair1.first << " " << pair1.second << endl;
実行結果は次のとおりです。
new pair1: Java教程 http://c.biancheng.net/java/
同時に、上記のプログラムでのpair4オブジェクトの作成プロセスは、完全に同等の次の形式で記述することもできます。
pair <string, string> pair4 = make_pair("C++教程", "http://c.biancheng.net/cplus/");
cout << "pair4: " << pair4.first << " " << pair4.second << endl;
<utility>
ヘッダー ファイルでペア オブジェクトを作成するためのメソッドを提供することに加えて、<、<=、>、>=、==、!=
これら 6 つの演算子はペア オブジェクト用にオーバーロードされています。操作規則は次のとおりです: 比較される 2 つのペア オブジェクトについては、まず、pair.first 要素のサイズを比較します。が等しい場合は、pair.second 要素のサイズの比較を続けます。
比較される 2 つのペア オブジェクトでは、対応するキーと値の型が同じであることに注意してください。そうでない場合は比較可能性がなくなり、コンパイラは一致する演算子がない、つまり適切なオーバーロードされた演算子が見つからないことを示すプロンプトを表示します。
例えば:
#include <iostream>
#include <utility> // pair
#include <string> // string
using namespace std;
int main() {
pair <string, int> pair1("STL教程", 20);
pair <string, int> pair2("C++教程", 20);
pair <string, int> pair3("C++教程", 30);
// pair1和pair2的key不同,value相同
if (pair1 != pair2) {
cout << "pair != pair2" << endl;
}
// pair2和pair3的key相同,value不同
if (pair2 != pair3) {
cout << "pair2 != pair3" << endl;
}
return 0;
}
プログラムの実行結果は次のようになります。
pair != pair2
pair2 != pair3
- 最後に、ペア クラス テンプレートには、2 つのペア オブジェクトのキーと値のペアを交換できる swap() メンバー関数も提供されていることを指摘しておく必要があります。操作が成功する前提は、2 つのオブジェクトのキーと値の型が一致していることです。ペアのオブジェクトは同じである必要があります。例えば:
#include <iostream>
#include <utility> // pair
#include <string> // string
using namespace std;
int main() {
pair <string, int> pair1("pair", 10);
pair <string, int> pair2("pair2", 20);
// 交换 pair1 和 pair2 的键值对
pair1.swap(pair2);
cout << "pair1: " << pair1.first << " " << pair1.second << endl;
cout << "pair2: " << pair2.first << " " << pair2.second << endl;
return 0;
}
プログラムの実行結果は次のようになります。
pair1: pair2 20
pair2: pair 10