Text
In the C++ standard library, std::map
is an associative container that stores elements in ascending order of keys (key) and provides efficient keyword lookup functionality. However, novice developers sometimes fall into trouble because they misunderstand the behavior of the square bracket operator []
in std::map
. In fact, when using []
to access a non-existent key, std::map
inserts a new key-value pair, and the default constructor will be used to initialize the value type corresponding to that key.
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> myMap;
// Incorrect usage: assuming here that we are trying to access a non-existent key and assume it will return 0
std::cout << "Value for 'nonexistent_key': " << myMap["nonexistent_key"] << std::endl;
// In fact, the above line of code creates a new key-value pair, where the value is initialized by the default constructor of int (usually 0)
return 0;
}
Although the above code does not directly cause the program to crash, this implicit insertion behavior can lead to unexpected side effects in some cases, such as resource leaks or changes that do not meet expectations. Worse still, in a multithreaded environment, concurrent access to uninitialized memory areas may even cause the program to crash.
To prevent these problems, it is recommended to use std::map::find()
or std::map::count()
methods to check if the key exists, or explicitly insert elements using std::map::insert()
:
std::map<std::string, int> safeMap;
if (safeMap.count("nonexistent_key") == 0) {
std::cout << "Key does not exist." << std::endl;
} else {
std::cout << "Value for existing key: " << safeMap["nonexistent_key"] << std::endl;
}
// Or explicitly insert a key-value pair, specifying the initial value
safeMap.insert({ "new_key", 0 });
If the map container stores objects of pointer type, the implicit insertion behavior will save an uninitialized pointer, and any operation on this pointer will cause the program to crash.