map<int,int> default values

std::map<int,int> mapy;
++mapy[5];

Is it safe to assume that mapy[5] will always be 1? I mean, will mapy[5] always get the default value of 0 before '++', even if not explicitly declared, as in my code?


Solution 1:

As soon as you access the map with the [] operator, if the key doesn't exist it gets added. The int gets "value initialization" invoked - so it will get a value of 0.

Solution 2:

Yes, it is safe to assume.

The map's operator[] is specified thus:([map.access])

Effects: If there is no key equivalent to x in the map, inserts value_type(std::move(x), T()) into the map.
Returns: A reference to the mapped_type corresponding to x in *this.

T() uses value-initialisation for all T except void ([expr.type.conv]/2), and value-initialisation for a primitive results in zero-initialization ([dcl.init]/7).

Therefore, the expression evaluates to a reference to an object with value zero ([dcl.init]/5).

The operator++ call then increments that object to one, and evaluates to one.

(All references are C++11.)

Solution 3:

Rep_Movsd's answer is oversimplified and is likely to lead to numerous extremely dangerous misconceptions. Primitive data-types in C++ do not have initializers. Louis Brandy had a wonderful talk in which he discussed many common C++ errors made at Facebook and a misunderstanding of how std::map<>[] works was one of the errors that he discussed, this is an excellent resource although he doesn't go into detail as to how std::map<>[] actually works.

In general, ints are not initialized and are undefined like all primitive types. That being said when used with std::map<>[] the int has a default value of zero set through a process called value initialization. Value initialization is a process that actually works with structs in general. For instance,

struct Struct {
Struct() : memberVariable() {}
       int memberVariable;
};

Will always initialize the int to zero. If the member variables were other primitive types they would also have specific initialization values. For instance, the following types are initialized, through value initialization like so:

bool = false
float = 0.0f
enum = (enum type)0
pointer = null pointer
pointer to member = null member pointer

Be extremely careful when working with data that is not explicitly initialized. One last thing, consider the following code

map<string, int> myMap;
cout << myMap["Foo"];

This code not only will always initialize the integer to 0, but it will also insert 0 into the map. Just to quickly recap, primitive data types are undefined if not initialized, but in some instances such as with a struct or map value initialization will initialize the primitive data with a specific value.