1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

STL:mapの要素アクセス方法 at と operator[]

Last updated at Posted at 2020-08-31

STL のmapを使っていて頭に入れておくべきことがあったので、ここにメモしておきます。
std::mapの指定キーに対応する要素の参照を返す(要素へアクセスする)方法は大きく2つあります。
さあ、あなたはどっち?

map::at

1.存在しないキーを指定すると、std::out_of_rangeの例外を送出する
2.constmapにもアクセスできる
  mapをメンバ変数としていて、constメンバ関数の中でmapの要素にアクセスする時に使える。
  ※const参照渡しでも同様

例.
// mapにある要素の値を変数に代入したり
variable = map.at(key);

// ある値をmapにある要素に代入したり
map.at(key) = value;

// constなmap2を生成する
const std::map<key, value> map2(map);

// map2にある要素の値を変数に代入できる
variable = map2.at(key);

map::operator[]

1.存在しないキーを指定すると、自動でデフォルト値の要素が追加され、その参照を返す
2.constmapにはアクセスできない

例.
// mapにある要素の値を変数に代入したり
variable = map[Key];

// ある値をmapにある要素に代入したり
vector[Key] = value;

// constなmap2を生成する
const std::map<key, value> map2(map);

// コンパイルエラー
variable = map2[key];

サンプルコード

「え?どゆこと?」
そう思ったあなた、是非ご自身の環境で以下のコードを試してみて下さい。

sample.cpp
# include <iostream>
# include <map>
# include <stdexcept>

int main()
{
    // キー:文字列、値:intとしたmapを生成する. 
    std::map<std::string, int> sampleMap;

    // sampleMapに"John"をキーとした要素を詰める. 
    sampleMap.insert(std::make_pair("John", 5));

    // sampleMapに"Ken"をキーとした要素を詰める. 
    sampleMap["Ken"] = 10;

    std::cout << "###std::map::at" << std::endl;

    // at
    try
    {
        std::cout << sampleMap.at("John") << std::endl;
        std::cout << sampleMap.at("Ken") << std::endl;
        std::cout << sampleMap.at("Tom") << std::endl;

        // キーチェック時に例外を投げるため、この処理は実行されない. 
        std::cout << "Complete..." << std::endl;
    }
    catch (std::out_of_range& sampleException)
    {
        std::cout << "can't find the key!" << std::endl;
        std::cout << "Error : " << sampleException.what() << std::endl;
    }

    std::cout << std::endl << "###std::map::operator[]" << std::endl;

    // operator[]
    try
    {
        std::cout << sampleMap["John"] << std::endl;
        std::cout << sampleMap["Ken"] << std::endl;
        std::cout << sampleMap["Tom"] << std::endl;

        // キーチェック時に例外を投げず、自動追加されるデフォルト値が出力され、実行完了となる. 
        std::cout << "Complete..." << std::endl;
    }
    // キーチェック時に例外は投げない. 
    catch (std::out_of_range& sampleException)
    {
        std::cout << "can't find the key!" << std::endl;
        std::cout << "Error : " << sampleException.what() << std::endl;
    }

    std::cout << "End..." << std::endl;

    return 0;
}
出力.
### std::map::at
5
10
can't find the key!
Error : invalid map<K, T> key

### std::map::operator[]
5
10
0
Complete...
End...

あ、intだとデフォルト値は0なのね。

まとめ

vectorとは異なり、存在しないキーに対応する要素へアクセスを、上記2つのどちらで行っても、未定義処理が行われることはありません。
若干用途が異なるので、どちらを使うかはケースバイケースでしょうかね。

1
0
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?