C++ unordered_map 使用详解(含C++20新特性)

目录

查找元素

迭代器

容量

修改操作

通接口

哈希策略

观察器

std::swap(std::unordered_map)

std::erase_if (std::unordered_map)


简介

本篇博客介绍C++常用的无序关联容器unordered_mapunordered_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 => five
 1 => one
 2 => two
 3 => three
 4 => 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_type
    erase_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();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章