Iterators II

Map iterators are not random-access like vector iterators are, therefore an expression like m.begin() + 5 would be invalid if m is a map.

With vectors, you can get an iterator to a specific element with an expression like v.begin() + IDX where IDX is the index of an element. Getting an iterator to a specific element in a map can be done with an expression like m.find(KEY) where KEY is the value of a key associated with a key/value pair element.

With maps, the subscript operator and the find member function are not the same. The subscript operator gives you the value associated with a specified key. The find member function gives you an iterator to the key/value pair from the specified key.

Let's see some equivalent expressions for setting the value of a key/value pair in a map.

map<string, double> prices; /* Create and set value using subscript operator */ prices["bread"s] = 2.50; /* Find and set value using iterators */ map<string, double>::iterator it = prices.find("bread"s); it->second = 2.40; /* Same as above but all on one line */ prices.find("bread"s)->second = 2.40;

Another thing to note is that a map's subscript operator will create the element if it does not already exist. The find member function will fail if the element, specified by it's key, does not exist.

Using a range-based for loop works on maps, but if you wanted to use iterators, the code would look like this:

for (map<string, double>::iterator it = prices.begin(); it != prices.end(); ++it) cout << it->first << " : "s << it->second << endl;

The equivalent code using a ranged-based for loop would be:

for (pair<string, double> e : prices) cout << e.first << " : "s << e.second << endl;

A new operator you should notice here is ->, this is known as the "member access through pointer" operator.

Since an iterator is not an element value but merely "pointer" to an element value, the member access operator (denoted by a dot) will not work. The normal member access operator is used for accessing member variables of a variable: in the ranged-based for loop, e.first and e.second uses the member access operator to access the key and values stored in the pair. The -> operator is similar but is used for values that "point" to a location that contains the member variables.

Another way of explaining the difference is: the expression a.b means get value of variable b from inside variable a, and the expression a->b means get the value of variable b from inside the variable that is pointed to by a.

It will become apprant why iterators are useful later on, right now the only use of iterators for maps would be to use the erase member function.

The following statement will remove the key/value pair containing the key "bread" from the prices map:

prices.erase(prices.find("bread"s));

This will work if we know that the key "bread" exists, but if we are not sure if such a key exists we can use the following:

map<string, double>::iterator it = prices.find("bread"s); if (it != prices.end()) prices.erase(it);

You can actually erase a map element without using iterators:

prices.erase("bread"s);

This erases the element containing key "bread" if it exists.

A side note about maps: maps also contain size and clear member function just like vectors, you can use them to get the number of elements in the map and remove all elements from the map respectively.