目录

查找元素

迭代器

容量

修改操作

通接口

哈希策略

观察器

std::swap(std::unordered_map)

std::erase_if (std::unordered_map)


简介

本篇博客介绍C++常用的无序关联容器unordered_map。unordered_map是C++11正式加入的对hash_map的官方实现(之前标准C++没有hash_map的官方实现,我们使用的STL的hash_map并不是官方的)。从名字可以看出这个结构是无序的,底层设计思想和STL的hash_map一样。元素在内部不以任何特定顺序排序,而是放进桶中。元素放进哪个桶完全依赖于其键的哈希。这允许对单独元素的快速访问,因为一旦计算哈希,则它准确指代元素所放进的桶。unordered_map搜索、插入和元素移除拥有平均常数时间复杂度。

查找元素

at()用于访问指定元素

T& at( const Key& key );
const T& at( const Key& key ) const;

返回到等于 key 的键的元素的引用。若无该元素,则抛出 std::out_of_range 类型异常。

operator []用于访问或插入元素

T& operator[]( const Key& key );
T& operator[]( Key&& key );

返回等于 key 的键的值的引用。如果该键不存在,则执行插入,反之,则覆盖原来的值。

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>int main()
{std::unordered_map<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};std::cout << "initially:\n";for (const auto &pair : letter_counts) {std::cout << pair.first << ": " << pair.second << '\n';}letter_counts['b'] = 42;  // 更新既存值letter_counts['x'] = 9;  // 插入新值std::cout << "after modifications:\n";for (const auto &pair : letter_counts) {std::cout << pair.first << ": " << pair.second << '\n';}// 统计每个词的出现数// (首次调用 operator[] 以零初始化计数器)std::unordered_map<std::string, size_t>  word_map;for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence","this", "sentence", "is", "a", "hoax"}) {++word_map[w];}for (const auto &pair : word_map) {std::cout << pair.second << " occurrences of word '" << pair.first << "'\n";}
}输出:
initially:
a: 27
b: 3
c: 1
after modifications:
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'
2 occurrences of word 'this'

count() 返回特定键的元素数量

(1)size_type count( const Key& key ) const;
(2)template< class K > size_type count( const K& x ) const;

(1) 返回等于指定参数 key 的键的元素数,因为此容器不允许重复,故返回值为 0 或 1 。

(2) 返回键等于指定参数 x 的元素数。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。

find()寻找特定键的元素

(1)iterator find( const Key& key );
(2)const_iterator find( const Key& key ) const;
(3)template< class K > iterator find( const K& x );
(4)template< class K > const_iterator find( const K& x ) const;

(1-2) 寻找键等于 key 的的元素。

(3-4) 寻找键等于值 x 的元素。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。

#include <iostream>
#include <unordered_map>int main()
{
// 简单比较演示std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};auto search = example.find(2);if (search != example.end()) {std::cout << "Found " << search->first << " " << search->second << '\n';} else {std::cout << "Not found\n";}
}输出:
Found 2 b

contains()可检查容器是否含有特定键的元素

(1)bool contains( const Key& key ) const;
(2)template< class K > bool contains( const K& x ) const;

(1) 检查容器中是否有键等于 key 的元素。

(2) 检查是否有键等于值 x 的元素。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。

#include <iostream>
#include <unordered_map>int main()
{  std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};if (example.contains(2)) {std::cout << "Found\n";} else {std::cout << "Not found\n";}
}输出:
Found

find()的返回值是迭代器,若有元素,可以直接通过返回的迭代器获取元素信息。 而contains()的返回值是bool型,只用于确定是否包含该元素。

equal_range()返回匹配特定键的元素范围

(1)std::pair<iterator,iterator> equal_range( const Key& key );
(2)std::pair<const_iterator,const_iterator> equal_range( const Key& key ) const;
(3)template< class K >std::pair<iterator,iterator> equal_range( const K& x );
(4)template< class K >std::pair<const_iterator,const_iterator> equal_range( const K& x ) const;

(1-2) 返回容器中所有键等于 key 的元素范围。范围以两个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素。

(3-4) 返回含有容器中所有键等于 x 的元素的范围。此重载仅若有限定标识 Hash::is_transparent 与 KeyEqual::is_transparent 均合法并指代类型才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash ,还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数。

#include <iostream>
#include <unordered_map>int main()
{  std::unordered_map<int,char> map = {{1,'a'},{1,'b'},{1,'d'},{2,'b'}};auto range = map.equal_range(1);for (auto it = range.first; it != range.second; ++it) {std::cout << it->first << ' ' << it->second << '\n';}
}输出:
1 a

迭代器

begin() & cbegine()

iterator begin() noexcept;
const_iterator begin() const noexcept;
const_iterator cbegin() const noexcept;

返回指向 unordered_map 首元素的迭代器。若 unordered_map 为空,则返回的迭代器将等于 end()。

end() & cend()

iterator end() noexcept;
const_iterator end() const noexcept;
const_iterator cend() const noexcept;

返回指向 unordered_map 最后一个元素的之后的迭代器。此元素表现为占位符;试图访问它导致未定义行为。

#include <cmath>
#include <iostream>
#include <unordered_map>struct Node { double x, y; };int main() {Node nodes[3] = { {1, 0}, {2, 0}, {3, 0} };// mag 是将 Node 的地址映射到其在平面中的模的映射std::unordered_map<Node *, double> mag = {{ nodes,     1 },{ nodes + 1, 2 },{ nodes + 2, 3 }};// 将每个 y 坐标从 0 更改到模for(auto iter = mag.begin(); iter != mag.end(); ++iter){auto cur = iter->first; // 指向 Node 的指针cur->y = mag[cur]; // 可以也使用 cur->y = iter->second;}// 更新并打印每个结点的模for(auto iter = mag.begin(); iter != mag.end(); ++iter){auto cur = iter->first;mag[cur] = std::hypot(cur->x, cur->y);std::cout << "The magnitude of (" << cur->x << ", " << cur->y << ") is ";std::cout << iter->second << '\n';}// 以基于范围的 for 循环重复上述者for(auto i : mag) {auto cur = i.first;cur->y = i.second;mag[cur] = std::hypot(cur->x, cur->y);std::cout << "The magnitude of (" << cur->x << ", " << cur->y << ") is ";std::cout << mag[cur] << '\n';// 注意与 std::cout << iter->second << '\n'; 相反,上述的 // std::cout << i.second << '\n'; 不会打印更新的模}
}输出:
The magnitude of (1, 1) is 1.41421
The magnitude of (2, 2) is 2.82843
The magnitude of (3, 3) is 4.24264
The magnitude of (1, 1.41421) is 1.73205
The magnitude of (2, 2.82843) is 3.4641
The magnitude of (3, 4.24264) is 5.19615

容量

empty() 用于检查容器是否为空

bool empty() const noexcept;
[[nodiscard]] bool empty() const noexcept;

size() 返回容纳的元素数量

size_type size() const noexcept;

返回容器中的元素数,即std::distance(begin(), end()) 。

int main()
{ std::unordered_map<int,char> nums {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};std::cout << "nums contains " << nums.size() << " elements.\n";
}输出:
nums contains 4 elements.

max_size() 返回最大可容纳的元素数

size_type max_size() const noexcept;

返回根据系统或库实现限制的容器可包含的元素最大数量,即对于最大容器的 std::distance(begin(), end())  。

#include <iostream>
#include <unordered_map>int main()
{std::unordered_map<char,char> s;std::cout << "Maximum size of a 'unordered_map' is " << s.max_size() << "\n";
}输出:
Maximum size of a 'unordered_map' is 768614336404564650

修改操作

clear()

void clear() noexcept;

从容器去除所有元素。此调用后 size() 返回零。非法化任何指代所含元素的引用、指针或迭代器。可能亦非法化尾后迭代器。

insert()

(1)std::pair<iterator,bool> insert( const value_type& value );std::pair<iterator,bool> insert( value_type&& value );
(2)template< class P >std::pair<iterator,bool> insert( P&& value );
(3)iterator insert( const_iterator hint, const value_type& value );iterator insert( const_iterator hint, value_type&& value );
(4)template< class P >iterator insert( const_iterator hint, P&& value );
(5)template< class InputIt >void insert( InputIt first, InputIt last );
(6)void insert( std::initializer_list<value_type> ilist );
(7)insert_return_type insert(node_type&& nh);
(8)iterator insert(const_iterator hint, node_type&& nh);

若容器尚未含有带等价关键的元素,则插入元素到容器中。

(1-2) 插入 value 。重载 (2) 等价于 emplace(std::forward<P>(value)) ,且仅若 std::is_constructible<value_type, P&&>::value == true 才参与重载决议。

(3-4) 插入 value ,以 hint 为应当开始搜索的位置的非强制建议。重载 (4) 等价于 emplace_hint(hint, std::forward<P>(value)) ,且仅若 std::is_constructible<value_type, P&&>::value == true 才参与重载决议。

(5) 插入来自范围 [first, last) 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的。

(6) 插入来自 initializer_list ilist 的元素。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的。

(7) 若 nh 是空的结点句柄,则不做任何事。否则插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。

(8) 若 nh 是空的结点句柄,则不做任何事并返回尾迭代器。否则,插入 nh 所占有的元素到容器,若容器尚未含有拥有等价于 nh.key() 的关键的元素,并返回指向拥有等于 nh.key() 的关键的元素的迭代器(无关乎插入成功还是失败)。若插入成功,则从 nh 移动,否则它保持该元素的所有权。元素被插入到尽可能接近 hint 的位置。若 nh 非空且 get_allocator() != nh.get_allocator() 则行为未定义。

若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不受影响。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。若插入成功,则在结点把柄保有元素时获得的指向该元素的指针和引用被非法化,而在提取前获得的指向元素的指针和引用变得合法。

#include <string>
#include <iostream>
#include <unordered_map>int main ()
{std::unordered_map<int, std::string> dict = {{1, "one"}, {2, "two"}};dict.insert({3, "three"});dict.insert(std::make_pair(4, "four"));dict.insert({{4, "another four"}, {5, "five"}});bool ok = dict.insert({1, "another one"}).second;std::cout << "inserting 1 -> \"another one\" " << (ok ? "succeeded" : "failed") << '\n';std::cout << "contents:\n";for(auto& p: dict)std::cout << " " << p.first << " => " << p.second << '\n';
}输出:
inserting 1 -> "another one" failed
contents:5 => five1 => one2 => two3 => three4 => four

insert_or_assign()

(1)template <class M>pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
(2)template <class M>pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
(3)template <class M>iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
(4)template <class M>iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);

(1,3) 若等价于 k 的键已存在于容器中,则赋值 std::forward<M>(obj) 给对应于键 k 的 mapped_type 。若键不存在,则如同用 insert 插入从 value_type(k, std::forward<M>(obj)) 构造的新值。

(2,4) 同 (1,3) ,除了从 value_type(std::move(k), std::forward<M>(obj)) 构造被映射值。

若插入发生且导致容器的重哈希,则所有迭代器被非法化。否则迭代器不受影响。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。

#include <iostream>
#include <unordered_map>
#include <string>int main()
{std::unordered_map<std::string, std::string> myMap;myMap.insert_or_assign("a", "apple"     );myMap.insert_or_assign("b", "bannana"   );myMap.insert_or_assign("c", "cherry"    );myMap.insert_or_assign("c", "clementine");for (const auto &pair : myMap) {std::cout << pair.first << " : " << pair.second << '\n';}
}输出:
c : clementine
a : apple
b : bannana

emplace()

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

若容器中无拥有该关键的元素,则插入以给定的 args 原位构造的新元素到容器。

细心地使用 emplace 允许在构造新元素的同时避免不必要的复制或移动操作。 准确地以与提供给 emplace 者相同的参数,通过std::forward<Args>(args)... 转发调用新元素(即 std::pair<const Key, T> )的构造函数。 即使容器中已有拥有该关键的元素,也可能构造元素,该情况下新构造的元素将被立即销毁。

若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。

#include <iostream>
#include <utility>
#include <string>
#include <unordered_map>int main()
{std::unordered_map<std::string, std::string> m;// 使用 pair 的移动构造函数m.emplace(std::make_pair(std::string("a"), std::string("a")));// 使用 pair 的转换移动构造函数m.emplace(std::make_pair("b", "abcd"));// 使用 pair 的模板构造函数m.emplace("d", "ddd");// 使用 pair 的逐片构造函数m.emplace(std::piecewise_construct,std::forward_as_tuple("c"),std::forward_as_tuple(10, 'c'));// C++17 起,能使用 m.try_emplace("c", 10, 'c');for (const auto &p : m) {std::cout << p.first << " => " << p.second << '\n';}
}输出:
a => a
b => abcd
c => cccccccccc
d => ddd
#include <unordered_map>
#include <iostream>
#include <utility>int main()
{std::unordered_map<int, int> numbers;std::cout << "Initially, numbers.empty(): " << numbers.empty() << '\n';numbers.emplace(42, 13);numbers.insert(std::make_pair(13317, 123));  std::cout << "After adding elements, numbers.empty(): " << numbers.empty() << '\n';
}输出:
Initially, numbers.empty(): 1
After adding elements, numbers.empty(): 0

emplace_hint()

template <class... Args>
iterator emplace_hint( const_iterator hint, Args&&... args );

插入新元素到容器,以 hint 为应当放置新元素位置的建议。原位构造元素,即不进行复制或移动操作。

准确地以与提供给函数者相同的参数,以 std::forward<Args>(args)... 转发调用元素类型( value_type 即 std::pair<const Key, T> )的构造函数。

若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。

try_emplace()

(1)template <class... Args>pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
(2)template <class... Args>pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
(3)template <class... Args>iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
(4)template <class... Args>iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);

(1) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。

(2) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(std::move(k)), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。

(3) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace_hint ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。

(4) 若容器中已存在等价于 k 的关键,则不做任何事。否则行为类似 emplace_hint ,除了以 value_type(std::piecewise_construct, std::forward_as_tuple(std::move(k)), std::forward_as_tuple(std::forward<Args>(args)...)) 构造元素。

若因插入发生重哈希,则所有迭代器都被非法化。否则迭代器不受影响。引用不被非法化。重哈希仅若新元素数量大于 max_load_factor()*bucket_count() 才发生。

#include <iostream>
#include <utility>
#include <string>#include <unordered_map>
int main()
{using namespace std::literals;std::unordered_map<std::string, std::string> m;m.try_emplace("a", "a"s);m.try_emplace("b", "abcd");m.try_emplace("c", 10, 'c');m.try_emplace("c", "Won't be inserted");for (const auto &p : m) {std::cout << p.first << " => " << p.second << '\n';}
}输出:
a => a
b => abcd
c => cccccccccc

erase()

(1)iterator erase( const_iterator pos );
(2)iterator erase( const_iterator first, const_iterator last );
(3)size_type erase( const key_type& key );

从容器移除指定的元素。

(1) 移除位于 pos 的元素。

(2) 移除范围 [first; last) 中的元素,它必须是 *this 中的合法范围。

(3) 移除键等于 key 的元素(若存在一个)。

到被去除元素的引用和迭代器被非法化,其他迭代器和引用不被非法化。迭代器 pos 必须合法且可解引用,从而使得 end() 迭代器(合法,但不可解引用)不能用作 pos 所用的值。保留未被擦除的元素顺序(这使得可能在迭代通过容器时擦除单独的元素)。

#include <unordered_map>
#include <iostream>
int main()
{std::unordered_map<int, std::string> c = {{1, "one"}, {2, "two"}, {3, "three"},{4, "four"}, {5, "five"}, {6, "six"}};// 从 c 擦除所有奇数for(auto it = c.begin(); it != c.end(); )if(it->first % 2 == 1)it = c.erase(it);else++it;for(auto& p : c)std::cout << p.second << ' ';
}输出:
two four six

swap()

void swap( unordered_map& other );
void swap( unordered_map& other ) noexcept();

将内容与 other 的交换,不在单个元素上调用任何移动、复制或交换操作。所有迭代器和引用保持合法,尾后迭代器被非法化。

Hash 和 KeyEqual 对象必须可交换 (Swappable) ,并用非成员 swap 的非限定调用交换它们。

extract()

(1)node_type extract( const_iterator position );
(2)node_type extract( const key_type& x );

(1) 解链含 position 所指向元素的结点并返回占有它的结点句柄。

(2) 若容器拥有元素而其关键等于 x ,则从容器解链该元素并返回占有它的结点句柄。否则,返回空结点把柄。任何情况下,均不复制或移动元素,只重指向容器结点的内部指针。

释出结点只会非法化指向被释出元素的迭代器,并保持未被去除元素的相对顺序。指向被释出元素的指针和引用保持合法,但在结点句柄占有该元素时不能使用:若元素被插入容器,就能使用它们。

注意:extract 是更换键而不重分配的唯一方式。

unordered_map<int, string> m{{1, "mango"}, {2, "papaya"}, {3, "guava"}};
auto nh = m.extract(2);
nh.key() = 4;
m.insert(move(nh));

merge()

(1)template<class H2, class P2>void merge(std::unordered_map<Key, T, H2, P2, Allocator>& source);
(2)template<class H2, class P2>void merge(std::unordered_map<Key, T, H2, P2, Allocator>&& source);
(3)template<class H2, class P2>void merge(std::unordered_multimap<Key, T, H2, P2, Allocator>& source);
(4)template<class H2, class P2>void merge(std::unordered_multimap<Key, T, H2, P2, Allocator>&& source);

试图释出("接合") source 中每个元素,并用 *this 的哈希函数和关键相等谓词插入到 *this 。 若 *this 中有元素,其关键等价于来自 source 中元素的关键,则不从 source 释出该元素。 不复制或移动元素,只会重指向容器结点的内部指针。指向被转移元素的所有指针和引用保持合法,但现在指代到 *this 中而非到 source 中。指代被转移元素的迭代器和所有指代到 *this 的迭代器被非法化。指向留在 source 中元素的迭代器保持合法。若 get_allocator() != source.get_allocator() 则行为未定义。

通接口

begin() & cbegin()

local_iterator begin( size_type n );
const_local_iterator begin( size_type n ) const;
const_local_iterator cbegin( size_type n ) const;

返回指向下标为 n 的桶首元素的迭代器。

end() & cend()

local_iterator end( size_type n );
const_local_iterator end( size_type n ) const;
const_local_iterator cend( size_type n ) const;

返回后随下标为 n 的桶的最后元素的元素的迭代器。此元素表现为占位符,试图访问它会导致未定义行为。

bucket_count() 返回容器中的桶数

size_type bucket_count() const;

max_bucket_count() 返回容器由于系统或库实现限制的能保有的最大桶数

size_type max_bucket_count() const;

bucket_size() 返回下标为 n 的桶中的元素数

size_type bucket_size( size_type n ) const;

bucket() 返回关键 key 的桶的下标

size_type bucket( const Key& key ) const;

始终会在此桶中找到关键等于 key 的元素(若存在)。返回值仅对 bucket_count() 返回相同值的容器实例合法。若 bucket_count() 为零则行为未定义。

哈希策略

load_factor() 

float load_factor() const;

返回每个桶元素的平均数,即 size() 除以 bucket_count() 。

max_load_factor()

(1)float max_load_factor() const;
(2)void max_load_factor( float ml );

管理最大加载因子(每个桶的平均元素数)。若加载因子超出此阈值,则容器自动增加桶数。

(1) 返回最大加载因子。

(2) 设置最大加载因子为 ml 。

rehash()

void rehash( size_type count );

设置桶数为 count 并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中。若新的桶数使加载因子大于最大加载因子( count < size() / max_load_factor() ),则新桶数至少为 size() / max_load_factor() 。

reserve()

void reserve( size_type count );

设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数,并重哈希容器,即考虑桶数已更改后将元素放进适合的桶。等效地调用 rehash(std::ceil(count / max_load_factor())) 。

观察器

hash_function() 返回对关键哈希的函数

hasher hash_function() const;

key_eq() 返回比较关键相等性的函数

key_equal key_eq() const;

std::swap(std::unordered_map)

(1)template< class Key, class T, class Hash, class KeyEqual, class Alloc >void swap( unordered_map<Key,T,Hash,KeyEqual,Alloc>& lhs, unordered_map<Key,T,Hash,KeyEqual,Alloc>& rhs );
(2)template< class Key, class T, class Hash, class KeyEqual, class Alloc >void swap( unordered_map<Key,T,Hash,KeyEqual,Alloc>& lhs, unordered_map<Key,T,Hash,KeyEqual,Alloc>& rhs ) noexcept(/* see below */);

为 std::unordered_map 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

std::erase_if (std::unordered_map)

template< class Key, class T, class Hash, class KeyEqual, class Alloc, class Pred >
typename std::unordered_map<Key,T,Hash,KeyEqual,Alloc>::size_typeerase_if(std::unordered_map<Key,T,Hash,KeyEqual,Alloc>& c, Pred pred);   (C++20 起)

从容器中去除所有满足谓词 pred 的元素。等价于:

auto old_size = c.size();for (auto i = c.begin(), last = c.end(); i != last; ) {if (pred(*i)) {i = c.erase(i);} else {++i;}}
return old_size - c.size();

C++ unordered_map 使用详解(含C++20新特性)相关推荐

  1. C++ map 使用详解(含C++20新特性)

    目录 访问元素 迭代器 容量 修改操作 查找 std::swap(std::map) std::erase_if (std::map) 简介 map 是一个关联容器,它提供一对一的数据处理能力(其中第 ...

  2. C++ std::thread 和 std::jthread 使用详解 (含C++20新特性)

    目录 std::thread std::thread 构造函数 观察器 操作 std::jthread std::jthread 构造函数 观察器 操作 停止记号处理 管理当前线程的函数 yield( ...

  3. C++ string 使用详解(含C++20新特性)

    目录 元素访问 迭代器 容量 操作 查找 std::erase, std::erase_if (std::basic_string) std::basic_string 简介 basic_string ...

  4. 详解16个CSS新特性(2021最新版-下)

    2021 CSS 的新特性和之前两年的相比有相似也有不同,本文就带大家继续看今年的 CSS 到底说了什么. 上篇指路:详解16个CSS新特性(2021最新版-上) CSS 等比缩放 CSS 等比缩放一 ...

  5. HDFS(下):NameNode和SecondaryNameNode、HDFS工作机制、故障处理、集群安全模式、服役退役节点、集群黑白名单、DataNode多目录详解、HDFS2.x新特性

    接上篇,上篇文章传送门:HDFS(上):HDFS优缺点.HDFS操作.HDFS客户端操作.HDFS的API.HDFS数据流.HDFS的IO流.HDFS读写数据流程.HDFS文件处理详解.windows ...

  6. 万字详解,JDK1.8新特性的Lambda、Stream和日期的使用详解

    前言 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScr ...

  7. mysql insert 不需要日志_详解MySQL|你不知道的新特性-8.0错误日志增强

    MySQL 8.0 重新定义了错误日志输出和过滤,改善了原来臃肿并且可读性很差的错误日志. 比如增加了 JSON 输出,在原来的日志后面以序号以及 JSON 后缀的方式展示. 比如我机器上的 MySQ ...

  8. Zabbix+MatrixDB大规模监控与分析解决方案详解(含PPT)

    首先,谢谢原作者:(此文为转载的文章,现将原地址贴出如下:以下文章来源于yMatrix,作者MatrixDB团队Zabbix+MatrixDB大规模监控与分析解决方案详解(含PPT)) 更多精彩Zab ...

  9. C++11、C++14、C++17、C++20新特性总结(5万字详解)

    文章目录 C++ 11是什么,C++ 11标准的由来 C++ auto类型推导完全攻略 auto 类型推导的语法和规则 auto 的高级用法 auto 的限制 auto 的应用 使用 auto 定义迭 ...

最新文章

  1. Java的后缀分类_java数据类型扩展及相应的面试题
  2. 给你一份长长长的 Spring Boot 知识清单(上)
  3. 简单shell 学习
  4. java 排序stackoverflow_JAVA开发知识点
  5. bde oracle 商友的流程_BorlandC++使用BDE访问Oracle方法
  6. 智能搜索推荐一体化营收增长解决方案
  7. Bootstrap组件_警告框
  8. html vue分页,Vue.js bootstrap前端实现分页和排序
  9. 获取socket对应的接收缓冲区中的可读数据量
  10. java xss 默认值_一台 Java 服务器可以跑多少个线程?
  11. input里面只有name属性 可以用id定位么_Selenium元素定位 提高篇 CSS定位元素
  12. ASP.NET Core中使用GraphQL - 第三章 依赖注入
  13. 64位centos下QQ无法输入中文只能输入英文
  14. .NET Remoting Basic(4)-客户端调用方式
  15. html5书法风格,中国书法五种分类介绍
  16. 禁忌搜索算法代码注释
  17. 人工智能/机器人/工程类投稿期刊、会议推荐
  18. 深度学习中优化方法——momentum、Nesterov Momentum、AdaGrad、Adadelta、RMSprop、Adam
  19. 计算机网络实验:无线组网
  20. java.lang.IllegalArgumentException: No converter found for return value of type: class com.sail.comm

热门文章

  1. 《openssl 编程》之 RSA(转)
  2. Kafka设计解析(四):Kafka Consumer解析
  3. 计算机专业有什么血泪建议吗?
  4. 那些年我们一起追过的大佬
  5. 音视频技术开发周刊 | 175
  6. 【线上分享】短视频出海 — 用户体验衡量关键指标与优化策略
  7. 北京大学数字视频编解码技术国家工程实验室开源AVS2高清实时编码器
  8. 剑指offer之题解目录(全)
  9. 免费开放阅读 | 数据库管理系统的事务原理(上)
  10. SRS提供的librtmp