Why Does Std::Map Operator[] Create an Object If the Key Doesn't Exist

std::map.operator[] not working with global maps

The operator[] in std::map is defined to return a reference to the object with the given key - or create it, if it doesn't exist, which modifies the map, that's why it's not a const method. There is no const version of that operator, that's why you get the shown error.

Use std::map's at(...) function for access-only. Note that it throws a std::out_of_range exception if the given key is not contained in the map; in C++20 or later you can use contains() to check whether the given key exists.

What happens if I read a map's value where the key does not exist?

The map::operator[] searches the data structure for a value corresponding to the given key, and returns a reference to it.

If it can't find one it transparently creates a default constructed element for it. (If you do not want this behaviour you can use the map::at function instead.)

You can get a full list of methods of std::map here:

http://en.cppreference.com/w/cpp/container/map

Here is the documentation of map::operator[] from the current C++ standard...

23.4.4.3 Map Element Access

T& operator[](const key_type& x);

  1. Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.

  2. Requires: key_type shall be CopyConstructible and mapped_type shall be DefaultConstructible.

  3. Returns: A reference to the mapped_type corresponding to x in *this.

  4. Complexity: logarithmic.

T& operator[](key_type&& x);

  1. Effects: If there is no key equivalent to x in the map, inserts value_type(std::move(x), T()) into the map.

  2. Requires: mapped_type shall be DefaultConstructible.

  3. Returns: A reference to the mapped_type corresponding to x in *this.

  4. Complexity: logarithmic.

std::map operator[] and automatically created new objects

The new object, when inserted into the map by [] operator, is value-initialized. It is ensured by the map implementation, i.e. it is done "automatically" in that sense. For objects of type DWORD (assuming it is a scalar type), value-initialization means zero-initialization.

By definition given in 23.3.1.2, operator [] is a shorthand for

(*((insert(make_pair(x, T()))).first)).second

The T() bit is the new object, which will turn into DWORD() in your case. DWORD() is guaranteed to be zero.

initialize std::map value when its key does not exist

may I know where I can find a reference for this claim?

This is what the C++11 Standard mandates. Per paragraph 23.4.4.3:

T& operator[](const key_type& x);

1 Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.

[...]

T& operator[](key_type&& x);

5 Effects: If there is no key equivalent to x in the map, inserts value_type(std::move(x), T()) into
the map.

Concerning the second question:

Is there any way to invoke the one-argument constructor of map's Value(s) ?

You could do this in C++03:

void some_other_add(int j, int k) {
myMap.insert(std::make_pair(j, Value(k)));
}

And use the emplace() member function in C++11:

myMap.emplace(j, k);

What does the STL map[key] return if the key wasn't a initialized key in the map?

A default constructed std::string ins inserted into the std::map with key 'b' and a reference to that is returned.

It is often useful to consult the documentation, which defines the behavior of operator[] as:

Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object, operator[] inserts the default object data_type().

(The SGI STL documentation is not documentation for the C++ Standard Library, but it is still an invaluable resource as most of the behavior of the Standard Library containers is the same or very close to the behavior of the SGI STL containers.)

Adding an object to std::map doesn't work unless an empty (no args) constructor for the class' object exists

operator[] requires that the type is DefaultConstructible, if the key does not exist.

On line params[name] = data;

  1. operator[] creates an element using the default constructor
  2. operator[] returns a reference to the element
  3. data is assigned to the reference, using the copy constructor

In your case, the step 1 fails because there is no default constructor.

C++17 adds insert_or_assign(), which does not require the type to be DefaultConstructible.

How to add to std::map an object with constant field?

Use map::emplace to construct A in-place:

myMap.emplace("Hello", 3);

Demo.

If the key doesn't exist in a map, then assignment means "add pair
[key, value] to the map". But if the key exists, then replace the
value.

As @Serge Ballesta commented, when the key already exists, you need to erase the node from the map and emplace a new node:

const char* key = "Hello";
const int value = 3;
const auto it = myMap.find(key);
if (it != myMap.end())
myMap.erase(it);
myMap.emplace(key, value);


Related Topics



Leave a reply



Submit