## 9.2 map 演算と multimap 演算

map および multimap データ型で提供されるメンバー関数の詳細を簡単に説明します。メンバー関数が基本演算を提供する一方で、データ構造のユーティリティは、第 IV 部で説明する汎用アルゴリズムを使用することによって、大幅に拡張できることに注意してください。

### 9.2.1 map の宣言と初期化

map の宣言は、標準 C++ ライブラリで繰り返し見てきたパターンに従います。map はテンプレートデータ構造で、キー要素の型、関連付けられた値の型、比較キーで使用される演算子によって特殊化されます。比較キーは省略可能です。C++ の比較的新しい機能であり, 一部のベンダーではサポートされていないデフォルトのテンプレート型を使用中のコンパイラがサポートしていない場合は、使用する必要がありません。この場合、キー型には小なり演算子が仮定されます。

map は初期要素なしで宣言することも、1 組の反復子を使用することによって他のコンテナから初期化することもできます。後者の場合、反復子が pair 型の値を示す必要があり、各組の最初のフィールドがキーとなり、2 番目のフィールドが値として使用されます。また、コピーコンストラクタを使用すると、他の map のコピーとなる map を作成することができます。

    // インデックスが double で値が文字列の map
     map<double, string, less<double> > map_one;
    // インデックスが 整数で値が整数の map
    map<int, int> map_two(aContainer.begin(), aContainer.end());
    // 新しい map を作成、２番目に作成した map で初期化
    map<int, int> map_three (map_two);   // コピーコンストラクタ

map は他の map に代入することが可能で、2 つの map は、他の標準 C++ ライブラリコンテナと同様に、`swap()` 演算を使用して値を交換することができます。

### 9.2.2 型の定義

クラス map と multimap には多数の型の定義が含まれ、一般的には宣言文で使用されます。たとえば、`integer` への `string` の map の反復子は、次のように宣言することができます。

    map<string, int>::iterator location;

`iterator` に加えて、表 14 では次の型を定義します。

#### 表 14 -- クラス map とクラス multimap の型の定義

型 | 定義
--- | ---
`key_type` | map のインデックス付けに使用されるキーに関連付けられた型
`value_type` | コンテナで保持される型、キーと値の組み合わせ
`mapped_type` | 値に関連付けられた型
`const_iterator` | 配下のシーケンスの変更を許可しない反復子
`reverse_iterator` | 逆方向に移動する反復子
`const_reverse_iterator` | 定数反復子と逆方向反復子の組み合わせ
`reference` | 配下の値への参照
`const_reference` | 要素が変更されることを許可しない配下の値への参照
`size_type` | 符号なし整数型、コンテナのサイズを示すために使用される
`key_compare` | 2 つのキーの比較に使用できる関数オブジェクト
`value_compare` | 2 つの要素の比較に使用できる関数オブジェクト
`difference_type` | 符号付き整数型、反復子間の距離の記述に使用される
`allocator_type` | コンテナによってすべての記憶管理に使用されるアロケータ

### 9.2.3 挿入とアクセス

値は、`insert()` 演算を使用して map または multimap に挿入することができます。引数は、キーと値の組み合わせの pair にする必要があることに注意してください。この pair は、map に関連付けられたデータ型 `value_type` を使用して作成されることもあります。

    map_three.insert (map<int>::value_type(5, 7));

また、たとえば他の map によって生成される反復子の組み合わせを使用して、挿入を実行することもあります。

    map_two.insert (map_three.begin(), map_three.end());

multimap ではなく、map を使用すると、添字演算子を使用して値にアクセスしたり、挿入したりすることができます。単純にキーを添字として使用すると、関連付けられた値を用いたデフォルト要素を持つエントリが作成されます。添字式の結果に値を割り当てると、関連付けられた結合が変更されます。

    cout << "Index value 7 is " << map_three[7] << endl;
       // 関連付けられた値を変更する
    map_three[7] = 5;
    cout << "Index value 7 is " << map_three[7] << endl;

### 9.2.4 値の削除

キー値の名前を付けることよって map または multimap から値を削除することができます。multimap では、消去によって要素とそれに関連付けられたキーのすべてが削除されます。また、`find()` 演算で算出される反復子と同様に、削除される要素を反復子によって示すこともできます。1 組の反復子を、範囲全体の要素を消去するために使用することができます。

    // 4 番目の要素 4 を消去する
    map_three.erase(4);
    // 5 番目の要素を消去する
    mtesttype::iterator five = map_three.find(5);
    map_three.erase(five);

    // 7 番目の要素と 11 番目の要素の間のすべての値を消去する
    mtesttype::iterator seven = map_three.find(7);
    mtesttype::iterator eleven = map_three.find(11);
    map_three.erase (seven, eleven);

配下の要素型にデストラクタがある場合、コレクションからキーと値の組み合わせが削除される前に、デストラクタが呼び出されます。

### 9.2.5 反復子

メンバー関数 `begin()` と `end()` は map と multimap の両方のための双方向反復子を作成します。map または multimap のいずれかへの反復子の間接参照は、キー/値の要素の pair を算出します。個々のフィールドにアクセスするために、フィールド名 `first` と `second` をこれらの値に適用することができます。最初のフィールドは定数であり、変更することはできません。一方、2 番目のフィールドは、指定されたキーとの関連付けで保持される値の変更に使用することができます。要素はキーフィールドの順序付けに基づいて、純編成で生成されます。メンバー関数 `rbegin()` と `rend()` は、逆の順序で要素を算出する反復子を作成します。

> 注: vector や deque とは異なり、map からの要素の挿入または削除によって、コンテナの他の部分を参照する反復子が有効となることはありません。

### 9.2.6 検索とカウント

メンバー関数 `size()` は、コンテナに保持される要素数を算出します。コンテナが空白の場合、メンバー関数 `empty()` はブール値 true を返し、通常、ゼロに対する `size()` のテストよりも高速です。

メンバー関数 `find()` はキーの引数を使用し、関連付けられたキー/値の組み合わせを示す反復子を返します。multimap の場合、この最初の値が返されます。いずれの場合も、このような値が検出されない場合は、終了値の反復子が返されます。

    if (map_one.find(4) != map_one.end())
       cout << "contains a 4th element" << endl;

メンバー関数 `lower_bound()` は引数キーと一致する最初のエントリーを算出し、一方、メンバー関数 `upper_bound()` は、引数と一致する最後のエントリーを越えた後の最初の値を返します。最後に、メンバー関数 `equal_range()` は上限と下限を保持する 1 組の反復子を返します。この章の後の部分で、これらの手続きを使用する例を示します。

メンバー関数 `count()` は、引数として提供されるキー値と一致する要素の数を返します。map の場合、この値は必ず 0 か 1 となり、multimap の場合は、負ではない任意の値とすることができます。既定のキーによってインデックスが作成された要素がコレクションに含まれているかどうかを確認するだけの場合は、`find()` 関数を使用してシーケンスの終端反復子の結果をテストするよりも、`count()` を使用するほうが簡単なこともあります。

    if (map_one.count(4))
       cout << "contains a 4th element" << endl;

### 9.2.7 要素の比較

引数を使用しないメンバー関数 `key_comp()` と `value_comp()` は、キーの要素または値の型の比較に使用できる関数オブジェクトを返します。この比較で使用される値はコレクションに含める必要はありません。また、関数がコンテナに影響を与えることもありません。

    if (map_two.key_comp (i, j))
       cout << "element i is less than j" << endl;

### 9.2.8 その他の map 演算

map と multimap は順序付けられたコレクションであり、map の反復子は pair を返すため、第 IV 部で説明されている関数の多くは意味がないか、使用するのが困難です。ただし、いくつか例外もあります。関数 `for_each()`、`adjacent_find()`、`accumulate()` は、それぞれ独自の用途があります。いずれの場合にも、引数として使用される関数に引数として 1 組のキー/値を使用する必要があることに注意してください。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月