views:

1153

answers:

5

I have a std::map like this:

map<wstring,int> Scores;

It stores names of players and scores. When someone gets a score I would simply do:

Scores[wstrPlayerName]++;

When there is no element in the map with the key wstrPlayerName it will create one, but does it initialize to zero or null before the increment or is it left undefined?

Should I test if the element exists every time before increment?

+10  A: 

This will default-construct a new instance of value. For integers, the default construction is 0, so this works as intended.

hazzen
+18  A: 

operator[] looks like this:

Value& map<Key, Value>::operator[](const Key& key);

If you call it with a key that's not yet in the map, it will default-construct a new instance of Value, put it in the map under key you passed in, and return a reference to it. In this case, you've got:

map<wstring,int> Scores;
Scores[wstrPlayerName]++;

Value here is int, and ints are default-constructed as 0, as if you initialized them with int(). Other primitive types are initialized similarly (e.g., double(), long(), bool(), etc.).

In the end, your code puts a new pair (wstrPlayerName, 0) in the map, then returns a reference to the int, which you then increment. So, there's no need to test if the element exists yet if you want things to start from 0.

tgamblin
+3  A: 

You should not test if the item exists before incrementing it. The [] operator does exactly what you need it to do, as others have said.

But what if the default-constructed value wouldn't work for you? In your case the best way to find if the element already exists is to try to insert it. The insert member function for std::map returns a std::pair<iterator, bool>. Whether the insert succeeds or fails, the first element of the pair will point to the desired object (either your new one, or the one that was already present). You can then alter its value as you see fit.

Kristo
A: 

Thanks for the help.

So the std::maps set their primitive-type values to 0.

I just wondered because I thought primitive-type things are always undefined when created.

If I write something like:

int i;
i++;

The compiler warns me that i is undefined and when I run the program it is usually not zero.

Calmarius
It's actually a feature of the C++ language. If you explicitly call int's constructor (int i = int()) like std::map does it will be initialized to zero. A bare int i will still be uninitialized.
Kristo
indeed, because "int i;" won't default initialize the int (unlike class types). it will leave its value undefined. same: struct a { int i; }; << i's value is undefined. struct a { a():i() { } int i; }; << i's value is 0
Johannes Schaub - litb
+1  A: 

Check rules for initialization.

See section 4.9.5 Initialization of C++ Prog Lang or C++ std book. Depending on whether your variable is local, static, user-defined or const default initialization can happen.

In you case, int is called POD (Plain old Datatype). Any auto (created on heap / local variable) POD variable is not default initialized. Hence for you "i" above will not have value zero.

Always make an habit of initializing POD when defined in heap. You can even use int() to initialize value.

Ketan