はじめに
競技プログラミングでmap
を使っていますが、かなり適当に使っていたので少しでも理解するために手元で動かしました。
バージョン
> g++ --version
g++ (Homebrew GCC 9.3.0) 9.3.0
コード
#include <iostream>
#include <map>
int main(){
std::map<int, bool> mp;
// 分かる
std::cout << mp.count(1) << std::endl; // 0 ... ①
mp[1] = true;
std::cout << mp.count(1) << std::endl; // 1 ... ②
// 分からなかった
bool f = mp[0];
std::cout << mp.count(0) << std::endl; // 1 ... ③
mp[1] = false;
std::cout << mp.count(1) << std::endl; // 1 ... ④
return 0;
}
解説
①
std::cout << mp.count(1) << std::endl; // 0 ... ①
keyである1
が非存在なので戻り値は0
。
②
mp[1] = true;
std::cout << mp.count(1) << std::endl; // 1 ... ②
keyである1
が存在するので戻り値は1
。
③
bool f = mp[0];
std::cout << mp.count(0) << std::endl; // 1 ... ③
mp[0]
にまだ値格納してなくない?と思いました。
map::operatorで下記の記載があります。
If k does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value. Notice that this always increases the container size by one, even if no mapped value is assigned to the element (the element is constructed using its default constructor).
bool f = mp[0];
非存在のキーに対してアクセスがあった場合、デフォルト値が入るとのこと。
つまり、上記の代入時点でmp[0]
にデフォルト値(false
)が格納されています。
std::cout << mp.count(0) << std::endl; // 1 ... ③
よって、keyである0
が存在するので戻り値は1
。
④
mp[1] = false;
std::cout << mp.count(1) << std::endl; // 1 ... ④
bool
の俗に言うゼロ値であるfalse
が代入された時点で、keyが削除されるかと思っていましたが、そんなことはありませんでした。
keyである1
が存在するので戻り値は1
。
まとめ
-
map
はアクセスした時点でキーが存在する - ゼロ値が格納されたからといってキーが非存在になるわけではない