std::unordered_map operator[] 方法
- 自 C++11 起
// (1) Non const version only
T& operator[]( const Key& key );
// (2) Non const version only
T& operator[]( Key&& key );
返回一个引用,该引用指向与 key
等效的键所映射的值,如果该键不存在,则执行插入操作。
- 自 C++17 起
- C++17 之前
-
(1) 如果键不存在,则通过
std::piecewise_construct
、std::forward_as_tuple(key)
、std::tuple<>()
原位构造一个value_type
对象。此函数等效于return this->try_emplace(key).first->second;
。当使用默认分配器时,这将导致键从 key 复制构造,映射值进行值初始化。类型要求
value_type
必须是EmplaceConstructible
的,可从std::piecewise_construct
、std::forward_as_tuple(key)
、std::tuple<>()
构造。当使用默认分配器时,这意味着key_type
必须是CopyConstructible
,mapped_type
必须是DefaultConstructible
。
-
(2) 如果键不存在,则通过
std::piecewise_construct
、std::forward_as_tuple(std::move(key))
、std::tuple<>()
原位构造一个value_type
对象。此函数等效于return this->try_emplace(std::move(key)).first->second;
。当使用默认分配器时,这将导致键从 key 移动构造,映射值进行值初始化。类型要求
value_type
必须是EmplaceConstructible
的,可从std::piecewise_construct
、std::forward_as_tuple(std::move(key))
、std::tuple<>()
构造。当使用默认分配器时,这意味着key_type
必须是MoveConstructible
,mapped_type
必须是DefaultConstructible
。
-
(1) 如果键不存在,则通过
std::piecewise_construct
、std::forward_as_tuple(key)
、std::tuple<>()
原位构造一个value_type
对象。当使用默认分配器时,这将导致键从 key 复制构造,映射值进行值初始化。类型要求
value_type
必须是EmplaceConstructible
的,可从std::piecewise_construct
、std::forward_as_tuple(key)
、std::tuple<>()
构造。当使用默认分配器时,这意味着key_type
必须是CopyConstructible
,mapped_type
必须是DefaultConstructible
。
-
(2) 如果键不存在,则通过
std::piecewise_construct
、std::forward_as_tuple(std::move(key))
、std::tuple<>()
原位构造一个value_type
对象。当使用默认分配器时,这将导致键从 key 移动构造,映射值进行值初始化。类型要求
value_type
必须是EmplaceConstructible
的,可从std::piecewise_construct
、std::forward_as_tuple(std::move(key))
、std::tuple<>()
构造。当使用默认分配器时,这意味着key_type
必须是MoveConstructible
,mapped_type
必须是DefaultConstructible
。
如果发生插入操作并导致容器进行 rehash,则所有迭代器都会失效。
否则,迭代器不受影响。引用也不会失效。
仅当新元素数量大于 max_load_factor() * bucket_count()
时,才会发生重新哈希。
参数
key
- 要查找的元素的键
返回值
如果不存在具有 key
的元素,则为新元素的映射值提供的引用。
否则,为具有与 key
等效的键的现有元素提供的映射值引用。
复杂度
平均情况,常数 - O(1)。
最坏情况下,与容器的大小呈线性关系 - O(size())。
异常
如果任何操作抛出异常,则插入无效。
备注
operator[]
是非 const 的,因为它会在键不存在时插入该键。
如果此行为不理想,或者容器是 const 的,则可以使用 at()
。
在已发布的 C++11 和 C++14 标准中,此函数被指定需要 mapped_type
是 DefaultInsertable
,key_type
是 CopyInsertable
或 MoveInsertable
到 *this
。此规范存在缺陷,已通过 LWG 2469 修复,上述描述已纳入该问题的解决方案。
然而,一种实现(libc++)已知是通过两个独立的分配器 construct()
调用来构造 key_type
和 mapped_type
对象,这与其说是原位构造 value_type
对象,不如说是按已发布的标准所要求的。这与标准中描述的有所不同。
- 自 C++17 起
insert_or_assign()
返回的信息比 operator[]
多,并且不需要映射类型的默认可构造性。
示例
#include <iostream>
#include <string>
#include <unordered_map>
auto print = [](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::unordered_map<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};
print("letter_counts initially contains: ", letter_counts);
letter_counts['b'] = 42; // updates an existing value
letter_counts['x'] = 9; // inserts a new value
print("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::unordered_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 << " occurrences of word '" << word << "'\n";
}
}
letter_counts initially contains: {{a: 27}{b: 3}{c: 1}}
after modifications it contains: {{a: 27}{b: 42}{c: 1}{x: 9}}
2 occurrences of word 'a'
1 occurrences of word 'hoax'
2 occurrences of word 'is'
1 occurrences of word 'not'
3 occurrences of word 'sentence'
0 occurrences of word 'that'
2 occurrences of word 'this'