map
The map
and unordered_map
containers provide the subscript operator and a corresponding at
function (§ 9.3.2, p. 348), which are described in Table 11.6 (overleaf). The set
types do not support subscripting because there is no “value” associated with a key in a set
. The elements are themselves keys, so the operation of “fetching the value associated with a key” is meaningless. We cannot subscript a multimap
or an unordered_multimap
because there may be more than one value associated with a given key.
Like the other subscript operators we’ve used, the map
subscript takes an index (that is, a key) and fetches the value associated with that key. However, unlike other subscript operators, if the key is not already present, a new element is created and inserted into the map
for that key. The associated value is value initialized (§ 3.3.1, p. 98).
For example, when we write
map <string, size_t> word_count; // empty map
// insert a value-initialized element with key Anna; then assign 1 to its value
word_count["Anna"] = 1;
the following steps take place:
• word_count
is searched for the element whose key is Anna
. The element is not found.
• A new key-value pair is inserted into word_count
. The key is a const string
holding Anna
. The value is value initialized, meaning in this case that the value is 0.
• The newly inserted element is fetched and is given the value 1.
Because the subscript operator might insert an element, we may use subscript only on a map
that is not const
.
Subscripting a map
behaves quite differently from subscripting an array or vector:
Using a key that is not already present adds an element with that key to the map
.
Another way in which the map
subscript differs from other subscript operators we’ve used is its return type. Ordinarily, the type returned by dereferencing an iterator and the type returned by the subscript operator are the same. Not so for map
s: when we subscript a map
, we get a mapped_type
object; when we dereference a map
iterator, we get a value_type
object (§ 11.3, p. 428).
In common with other subscripts, the map
subscript operator returns an lvalue (§ 4.1.1, p. 135). Because the return is an lvalue, we can read or write the element:
cout << word_count["Anna"]; // fetch the element indexed by Anna; prints 1
++word_count["Anna"]; // fetch the element and add 1 to it
cout << word_count["Anna"]; // fetch the element and print it; prints 2
Unlike vector
or string
, the type returned by the map
subscript operator differs from the type obtained by dereferencing a map
iterator.
The fact that the subscript operator adds an element if it is not already in the map
allows us to write surprisingly succinct programs such as the loop inside our word-counting program (§ 11.1, p. 421). On the other hand, sometimes we only want to know whether an element is present and do not want to add the element if it is not. In such cases, we must not use the subscript operator.