std::map::operator[](3)
πΈ NAME
Okay bestie, this is std::map::operator[] from the C++ Standard Libary manual β page 3, and yes the header spelling is literally βLibaryβ and we are not touching it π
. Itβs the std::map operator that looks up a key, inserts a default value if the key isnβt there, and hands you back a reference. Iconic behavior β¨
β¨ Synopsis
T& operator[]( const Key& key ); (1)
T& operator[]( Key&& key ); (2) (since C++11)
template< class K > (3) (since C++26)
T& operator[]( K&& x );
This returns a reference to the value that is mapped to a key equivalent to key or x respectively, and it performs an insertion if such a key does not already exist. Slay π
Overload (1): Inserts value_type(key, T()) if the key does not exist.
key_typemust meet the requirements ofCopyConstructible.mapped_typemust meet the requirements ofCopyConstructibleand, until C++11,DefaultConstructible.
If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise) and a reference to it is returned.
Overload (1) also has a C++17-and-later description: it inserts a value_type object constructed in-place from std::piecewise_construct, std::forward_as_tuple(key), std::tuple<>() if the key does not exist. Itβs equivalent to:
return this->try_emplace(key).first->second;
(since C++17) When the default allocator is used, this results in the key being copy constructed from key and the mapped value being value-initialized.
- Since C++11,
value_typemust beEmplaceConstructiblefromstd::piecewise_construct,std::forward_as_tuple(key),std::tuple<>(). When the default allocator is used, this means thatkey_typemust beCopyConstructibleandmapped_typemust beDefaultConstructible.
Overload (2): Inserts a value_type object constructed in-place from std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::tuple<>() if the key does not exist. Itβs equivalent to:
return this->try_emplace(std::move(key)).first->second;
(since C++17) When the default allocator is used, this results in the key being move constructed from key and the mapped value being value-initialized.
value_typemust beEmplaceConstructiblefromstd::piecewise_construct,std::forward_as_tuple(std::move(key)),std::tuple<>(). When the default allocator is used, this means thatkey_typemust beMoveConstructibleandmapped_typemust beDefaultConstructible.
Overload (3): Inserts a value_type object constructed in-place if there is no key that transparently compares equivalent to the value x. Itβs equivalent to:
return this->try_emplace(std::forward<K>(x)).first->second;
This overload participates in overload resolution only if the qualified-id Compare::is_transparent is valid and denotes a type. It allows calling this function without constructing an instance of Key.
No iterators or references are invalidated. Periodt π
π§Έ Parameters
keyβ the key of the element to find.xβ a value of any type that can be transparently compared with a key.
π Return value
1,2β a reference to the mapped value of the new element if no element with keykeyexisted. Otherwise, a reference to the mapped value of the existing element whose key is equivalent tokey.3β a reference to the mapped value of the new element if no element with key that compares equivalent to the valuexexisted. Otherwise, a reference to the mapped value of the existing element whose key compares equivalent tox.
π Exceptions
If an exception is thrown by any operation, the insertion has no effect. The map stays unbothered, as it should. π
π¦ Complexity
Logarithmic in the size of the container.
π§ Notes
Back in the published C++11 and C++14 standards, this function was specified to require mapped_type to be DefaultInsertable and key_type to be CopyInsertable or MoveInsertable into *this. That spec was defective, bestie β it got fixed by LWG issue 2469, and the description above already incorporates the resolution of that issue.
However, one implementation (libc++) is known to construct the key_type and mapped_type objects via two separate allocator construct() calls, as arguably required by the standards as published, rather than emplacing a value_type object.
operator[] is non-const because it inserts the key if it doesnβt exist. If this behavior is undesirable, or if the container is const, at may be used.
insert_or_assign returns more information than operator[] and does not (since C++17) require default-constructibility of the mapped type.
Feature-test macro vibes:
- Feature-test macro:
__cpp_lib_associative_heterogeneous_insertion - Value:
202311L - Std:
(C++26) - Feature: Heterogeneous overloads for the remaining member functions in ordered and unordered associative containers.
(3)
π Example
The page has a // Run this code link; hereβs the whole thing, untouched:
#include <iostream>
#include <string>
#include <map>
void println(auto const comment, auto const& map)
{
std::cout << comment << '{';
for (const auto& pair : map)
std::cout << '{' << pair.first << ": " << pair.second << '}';
std::cout << "}\n";
}
int main()
{
std::map<char, int> letter_counts{{'a', 27}, {'b', 3}, {'c', 1}};
println("letter_counts initially contains: ", letter_counts);
letter_counts['b'] = 42; // updates an existing value
letter_counts['x'] = 9; // inserts a new value
println("after modifications it contains: ", letter_counts);
// count the number of occurrences of each word
// (the first call to operator[] initialized the counter with zero)
std::map<std::string, int> word_map;
for (const auto& w : {"this", "sentence", "is", "not", "a", "sentence",
"this", "sentence", "is", "a", "hoax"})
++word_map[w];
word_map["that"]; // just inserts the pair {"that", 0}
for (const auto& [word, count] : word_map)
std::cout << count << " occurrence(s) of word '" << word << "'\n";
}
π Output
letter_counts initially contains: {{a: 27}{b: 3}{c: 1}}
after modifications it contains: {{a: 27}{b: 42}{c: 1}{x: 9}}
2 occurrence(s) of word 'a'
1 occurrence(s) of word 'hoax'
2 occurrence(s) of word 'is'
1 occurrence(s) of word 'not'
3 occurrence(s) of word 'sentence'
0 occurrence(s) of word 'that'
2 occurrence(s) of word 'this'
π Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards:
- DR: LWG 334 β Applied to: C++98 β Behavior as published: the effect of overload (1) was simply returning
(*((insert(std::make_pair(x, T()))).first)).secondβ Correct behavior: provided its own description instead.
π See also
atβ access specified element with bounds checking (public member function).insert_or_assign(C++17)β inserts an element or assigns to the current element if the key already exists (public member function).try_emplace(C++17)β inserts in-place if the key does not exist, does nothing if the key exists (public member function).
Okay thatβs the whole page, bestie π«Ά. Source: http://cppreference.com Β· version/date: 2024.06.10 Β· page: std::map::operator[](3). Go forth and index responsibly π.
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms