はじめに
競技プログラミングで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はアクセスした時点でキーが存在する - ゼロ値が格納されたからといってキーが非存在になるわけではない