Counting entries
The length of a dictionary is the number of key-value pairs it holds. For an unordered_map, the member function size() returns that number. Every standard container works the same way, so the same call is used for a vector, a string and a map.
unordered_map<string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Charlie"] = 72;
int n = scores.size();
cout << n; // 3
Each pair counts once, no matter how large the value is. The keys and values are not added together, and a value such as 0 is still an entry. Only the number of keys matters.
The type of size()
size() returns an unsigned integer type, size_t, and the lesson stores it in an int. For a small map the conversion is harmless. In general code, the unsigned type has two traps. Subtraction on it can wrap: scores.size() - 5 is a huge positive number when the map has fewer than five entries. And comparing it with a negative int gives surprising answers, because the int is converted to unsigned first. When you are not certain, hold the result in a size_t or auto.
Checking for an empty map
To ask whether a dictionary has any entries, use empty(). It returns a bool:
cout << scores.empty(); // 0, which is false
unordered_map<string, int> none;
cout << none.size(); // 0
By default, cout prints a bool as 1 or 0. That is why the first line shows 0 for "not empty": the answer to "is it empty?" is false. Use if (scores.empty()) in conditions instead of scores.size() == 0. Both work, but empty() reads better, and for some containers it is cheaper.
The length changes as the map changes
size() always reflects the current contents:
- Adding a new key with
[]orinsertraises it by one. - Assigning to an existing key does not change it, since no new pair is created.
- Calling
erase(key)removes the pair and lowers it by one when the key was present. - Reading a missing key with
[]adds it, sosize()grows even though you only meant to read.
With the map above, scores["Zed"] followed by scores.size() gives 4, and the new pair is Zed with 0. This is a handy way to notice an accidental insert while debugging, and a good reason to use count or find for plain existence checks.
What the length is good for
The size answers questions such as "how many different words did I see?" or "how many students have a score?". Put each item into a map as a key, and the number of distinct keys is size(). Duplicates collapse into one entry, so the map removes them for you. Inserting "Alice" twice leaves the size at 1.
You do not need to count by looping over the map. A loop over the entries visits exactly size() pairs, but size() itself is a constant-time call. The map tracks its own count, so asking is cheap even when the map is large.
The exercise, step by step
The editor starts with a map named scores that holds three students. The task is to get the number of entries.
- Declare an
intnamedcount. The result is a whole number. - Call
size()on the map with a dot and empty parentheses:scores.size(). Assign that tocount.
unordered_map<string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Charlie"] = 72;
int count = scores.size();
The value of count is 3: Alice, Bob and Charlie. The map itself is unchanged. Reading its size has no effect on the contents.
Common mistakes
- Leaving out the parentheses.
scores.sizenames the function and does not call it, and the assignment will not compile. - Using
length()orlen. A string haslength(), but containers such asunordered_mapusesize(). - Using
sizeof(scores). That is the size in bytes of the map object itself, not the number of entries. - Assuming the count is the highest score or the sum of values. It counts keys.
- Subtracting from an unsigned size. Compare first, or convert to a signed type.
Key takeaways
m.size()is the number of key-value pairs, andm.empty()tells you whether there are none.- The result is unsigned, so be careful with subtraction and with comparisons against negative numbers.
- Adding a new key raises the size, updating an existing key does not, and a lookup with
[]can add a key by accident.