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);
Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.
Requires: key_type shall be CopyConstructible and mapped_type shall be DefaultConstructible.
Returns: A reference to the mapped_type corresponding to x in *this.
Complexity: logarithmic.
T& operator[](key_type&& x);
Effects: If there is no key equivalent to x in the map, inserts value_type(std::move(x), T()) into the map.
Requires: mapped_type shall be DefaultConstructible.
Returns: A reference to the mapped_type corresponding to x in *this.
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, insertsvalue_type(x, T())
into the map.[...]
T& operator[](key_type&& x);
5 Effects: If there is no key equivalent to
x
in the map, insertsvalue_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 objectdata_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;
operator[]
creates an element using the default constructoroperator[]
returns a reference to the elementdata
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
Scope of Using Declaration Within a Namespace
Does This Really Break Strict-Aliasing Rules
Why Is Modifying a String Through a Retrieved Pointer to Its Data Not Allowed
Why Do Functions Need to Be Declared Before They Are Used
Is a Constexpr Array Necessarily Odr-Used When Subscripted
What Is the Type of a String Literal in C++
Why Does a Std::Atomic Store with Sequential Consistency Use Xchg
Calling Initializer_List Constructor via Make_Unique/Make_Shared
Alternative Function in iOStream.H for Getch() of Conio.H
Detect When Multiple Enum Items Map to Same Value
"Observable Behaviour" and Compiler Freedom to Eliminate/Transform Pieces C++ Code
Correct Printf Format Specifier for Size_T: %Zu or %Iu
Undefined Reference to '_Stack_Chk_Fail'
Will C++ Exceptions Safely Propagate Through C Code