104
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?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Bill Kotsias
  • 3,258
  • 6
  • 33
  • 60
  • 3
    Possible duplicate of [std::map default value for build-in type](http://stackoverflow.com/questions/4523959/stdmap-default-value-for-build-in-type) – bobobobo Apr 21 '16 at 16:40
  • 6
    @bobobobo: this question is older than [std::map default value for build-in type](http://stackoverflow.com/questions/4523959/stdmap-default-value-for-build-in-type), then the duplicate one should be [std::map default value for build-in type](http://stackoverflow.com/questions/4523959/stdmap-default-value-for-build-in-type). – mpromonet Apr 22 '16 at 06:33

5 Answers5

149

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.

rep_movsd
  • 6,675
  • 4
  • 30
  • 34
  • Far as I've experienced, an uninitialized primitive `int`'s initial value is _undefined_ -- that is it can be 0, or it can be -99765521. Ever had an uninitialized `int` as a class variable and had one of those wacky values appear in your program? That said, I tested this and it seems to work. `#include #include using namespace std; int main() { map m ; for( int i = 0 ; i < 100 ; i++ ) m[i]++ ; for( const pair& p : m ) printf( "m[%d] => %d\n", p.first, p.second ) ; }` – bobobobo Jul 02 '13 at 13:43
  • 32
    It works in a different way than you think. int x; makes x get an undefined value int x = int(); Again x gets 0 class foo { int x; foo() : x() {} }; foo f; Here f.x will be zero – rep_movsd Jul 11 '13 at 18:40
  • @bobobobo: See my answer. Initialisation is more complex than that and has multiple "modes of operation" depending on context. – Lightness Races in Orbit May 16 '18 at 13:09
  • I thought the values in all containers are created in heap, and value in heap will be initialized with a appropriate value. In this case, 0. Is that right? – r0n9 Aug 01 '18 at 23:52
  • 1
    In C++ heap and stack memory are uninitialized - an object get initialized by its default constructor - the language has default constructors for primitive types that initialize them to 0 when you invoke it in the right way See my earlier comment – rep_movsd Aug 02 '18 at 13:37
  • The term 'default initializer' is scary and wrong here. The correct term is 'value initialization' and this is the reason why the map default values are 0. Primitive types do _not_ have a default constructor/initializer whatsoever which initializes them to zero. This would be useful, but this isn't the case. C++ initialization is very complex! – Johannes Overmann Jan 18 '22 at 16:17
  • 1
    @JohannesOvermann - corrected – rep_movsd Jan 20 '22 at 07:12
67

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.)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 3
    No idea why your answer was downvoted because you're correct. That's exactly what the specification says (just checked it myself). – Hans de Ruiter Jun 06 '18 at 04:38
10

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.

Rachel Casey
  • 205
  • 2
  • 11
  • 3
    _"Primitive data-types in C++ do not have initializers"_ This is oversimplified and is likely to lead to dangerous misconceptions. _"not initialized"_ No. Well, not quite. It's called _default-initialization_ but yes the result is an indeterminate value (C++11 8.5/11). _"are undefined"_ No. Indeterminate. _"structs"_ C++ does not have structs. _"value initialization"_ Correct. The key point is the different kind of initialization used. Also you have some comma splices in your prose. – Lightness Races in Orbit May 16 '18 at 13:00
  • Primitive datatypes are not initialized to any value by default. They do not have default construction. They do, in some instances, have value construction. The distinction you are trying to make between an undefined and indeterminate behavior is preposterous. As per the C++ 11 standard undefined behaviors is defined as: "...nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements" essentially meaning an error in either logic or state has occurred, and the result is unknown. I never said structs were from C++. – Rachel Casey May 16 '18 at 13:12
  • _"The distinction you are trying to make between an undefined and indeterminate behavior is preposterous."_ I didn't make the distinction, the standard did. If you think that is preposterous, you are of course free to raise an objection on the ISO working group mailing list. – Lightness Races in Orbit May 16 '18 at 13:13
  • _"I never said structs were from C++."_ If you already know this, then why did you talk about structs on a C++ question? Now _that's_ preposterous! – Lightness Races in Orbit May 16 '18 at 13:13
  • It is worth noting that structs are often used in C++ code, just as many aspects of the C language are still used in modern C++. The struct example is applicable to this question as C++ is backcapatable with C. If you are looking to write in some sort of "pure C++" language program in D. – Rachel Casey May 16 '18 at 13:19
  • 1
    No. It is not possible to create a struct in C++. It is only possible to create a class using the inherited `struct` keyword. The code you have shown contains a _class_. C++ does not have structs. Further reading: https://stackoverflow.com/a/36917400/560648 https://stackoverflow.com/a/34108140/560648 – Lightness Races in Orbit May 16 '18 at 13:23
  • Thanks for the reference. Question: Given that struct declares a class with default public members whereas class declares a class with default private members what is wrong with the code that I posted in my initial answer? – Rachel Casey May 16 '18 at 13:30
  • Nothing; the code is fine. It's the prose. _"Value initialization is a process that actually works with structs in general"_ Impossible since C++ does not have structs. – Lightness Races in Orbit May 16 '18 at 13:58
9

Yes, the default value will be the default of that type. If you want another default, you can create a class that behaves like an int but has a different default constructor.

Rasmus Kaj
  • 4,224
  • 1
  • 20
  • 23
3

The default value of the map<int,int> will be 0;

if you would like to change it to -1 then following method can help.

#include <bits/stdc++.h>
using namespace std;
  
struct AnotherVal{
    int value = -1; // can be changed as per requirement 
};
  

int main()
{
    map<int, AnotherVal> tempmap;
    cout << tempmap[1].value << endl;
  
    return 0;
} 

output:

-1

Hope, this will helps you!

Vaibhav Pallod
  • 466
  • 7
  • 21