目录

访问元素

迭代器

容量

修改操作

查找

std::swap(std::map)

std::erase_if (std::map)


简介

map 是一个关联容器,它提供一对一的数据处理能力(其中第一个称为键,每个键只能在 map 中出现一次,第二个称为该键的值,不同键的值可以相同),由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。

map 内部构建一棵红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在 map 内部所有的数据都是有序的。与另一个常用的容器 vector 相比,map 的优势体现在查询和删除操作上。由于 map 内部是一棵红黑树,所以查询操作的时间复杂度为O(logn)。map 在删除元素时,不需要移动大量的元素,虽然有时需要调整树的结构,但时间消耗远远小于 vector 移动元素的时间,时间复杂度为O(1)。

 

访问元素

at()用于访问指定元素

T& at( const Key& key );                    (since C++11)
const T& at( const Key& key ) const;        (since C++11)

返回对键值等于的元素映射值的引用 key。如果不存在这样的元素,则引发类型为std::out_of_range的异常。

 

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

T& operator[]( const Key& key );
T& operator[]( Key&& key );            (since C++11)

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

#include <iostream>
#include <string>
#include <vector>
#include <map>
 
int main()
{
    std::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;  // update an existing value
    letter_counts['x'] = 9;  // insert a new value
 
    std::cout << "after modifications:\n";
    for (const auto &pair : letter_counts) {
        std::cout << pair.first << ": " << pair.second << '\n';
    }
 
    // count the number of occurrences of each word
    // (the first call to operator[] initialized the counter with zero)
    std::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'

 

迭代器

begin() & cbegin()

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

将迭代器返回到的第一个元素 map如果的 map 值为空,则返回的迭代器将等于end()

 

end() & cend()

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

将迭代器返回到的最后一个元素之后的元素 map此元素充当占位符;尝试访问它会导致未定义的行为。

#include <iostream>
#include <map>
 
int main() {
  std::map<int, float> num_map;
  num_map[4] = 4.13;
  num_map[9] = 9.24;
  num_map[1] = 1.09;
  // calls a_map.begin() and a_map.end()
  for (auto it = num_map.begin(); it != num_map.end(); ++it) {
    std::cout << it->first << ", " << it->second << '\n';
  }
}

输出:
1, 1.09
4, 4.13
9, 9.24

 

rbegin() & crbegin()

reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator crbegin() const noexcept;

将反向迭代器返回给 reversed 的第一个元素 map它对应于 non-reversed 的最后一个元素 map。如果 map 为空,则返回的迭代器等于rend()

 

rend() & crend()

reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crend() const noexcept;

返回反向迭代器,该迭代器返回 reversed 的最后一个元素之后的元素 map。它对应于 non-reversed 的第一个元素之前的元素 map。该元素充当占位符,尝试访问它会导致未定义的行为。

 

容量

empty()检查容器是否无元素

[[nodiscard]] bool empty() const noexcept;
#include <map>
#include <iostream>
#include <utility>
 
int main()
{
    std::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

 

size()返回容器中的元素数

size_type size() const noexcept;
#include <map>
#include <iostream>
 
int main()
{ 
    std::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;
#include <iostream>
#include <map>
 
int main()
{
    std::map<char,char> s;
    std::cout << "Maximum size of a 'map' is " << s.max_size() << "\n";
}

输出:
Maximum size of a 'map' is 576460752303423487

 

修改操作

clear()

void clear() noexcept;

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

 

insert()

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

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

(1-3) 返回由指向被插入元素的迭代器(或阻止插入的元素的迭代器)和指代插入是否发生的 bool 组成的 pair 。

(4-6) 返回指向被插入元素的迭代器,或指向阻止插入的元素的迭代器。

(7-8) (无)

(9) 返回 insert_return_type ,其成员初始化如下:若 nh 为空,则 inserted 为 false , position 为 end() ,而 node 为空。否则发生插入, inserted 为 true , position 指向被插入元素,而 node 为空。若插入失败,则 inserted为 false , node 拥有 nh 的先前值,而 position 指向拥有等价于 nh.key() 的关键的元素。

(10) 若 nh 为空则为尾迭代器,若插入发生则为指向被插入元素的迭代器,而若插入失败则为指向拥有等价于 nh.key() 的关键的元素的迭代器。

常用实例:

// 定义一个map对象
map<int, string> Mapasd;
// 第一种 用insert函數插入pair
Mapasd.insert(pair<int, string>(0, "zero"));

// 第二种 用make_pair函数,无需写出型别, 就可以生成一个pair对象 
Mapasd.insert(make_pair(1, "qwe"));

// 第三种 用insert函数插入value_type数据
Mapasd.insert(map<int, string>::value_type(2, "student_one"));

// 第四种 用"array"方式插入
Mapasd[1] = "first";
Mapasd[2] = "second";

上面常用的三种方法,虽然都可以实现数据的插入,但是它们是有区别的,第一种和第二种在效果上是完成一样的,用insert函数插入数据,当map中存在该关键字时,insert 操作不再插入这条数据。但是用数组方式就不同了,它可以覆盖该关键字所对应的值。

 

#include <iomanip>
#include <iostream>
#include <map>
#include <string>
 
using namespace std::literals;
 
template<typename It>
void printInsertionStatus(It it, bool success)
{
    std::cout << "Insertion of " << it->first << (success ? " succeeded\n" : " failed\n");
}
 
int main()
{
    std::map<std::string, float> karasunoPlayerHeights;
 
    // 重载 3 :从右值引用插入
    const auto [it_hinata, success] = karasunoPlayerHeights.insert({"Hinata"s, 162.8});
    printInsertionStatus(it_hinata, success);
 
    {
        // 重载 1 :从左值引用插入
        const auto [it, success2] = karasunoPlayerHeights.insert(*it_hinata);
        printInsertionStatus(it, success2);
    }
    {
        // 重载 2 :经由转发到 emplace 插入
        const auto [it, success] = karasunoPlayerHeights.insert({"Kageyama", 180.6});
        printInsertionStatus(it, success);
    }
 
    {
        // 重载 6 :带位置提示从右值引用插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, {"Azumane"s, 184.7});
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
    {
        // 重载 4 :带位置提示从左值引用插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, *it_hinata);
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
    {
        // 重载 5 :带位置提示经由转发到 emplace 插入
        const std::size_t n = std::size(karasunoPlayerHeights);
        const auto it = karasunoPlayerHeights.insert(it_hinata, {"Tsukishima", 188.3});
        printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
    }
 
    auto node_hinata = karasunoPlayerHeights.extract(it_hinata);
    std::map<std::string, float> playerHeights;
 
    // 重载 7 :从范围插入
    playerHeights.insert(std::begin(karasunoPlayerHeights), std::end(karasunoPlayerHeights));
 
    // 重载 8 :从 initializer_list 插入
    playerHeights.insert({{"Kozume"s, 169.2}, {"Kuroo", 187.7}});
 
 
    // 重载 9 :插入结点
    const auto status = playerHeights.insert(std::move(node_hinata));
    printInsertionStatus(status.position, status.inserted);
 
    node_hinata = playerHeights.extract(status.position);
    {
        // 重载 10 :插入结点带位置提示
        const std::size_t n = std::size(playerHeights);
        const auto it = playerHeights.insert(std::begin(playerHeights), std::move(node_hinata));
        printInsertionStatus(it, std::size(playerHeights) != n);
    }
 
 
    // 打印结果 map
    std::cout << std::left << '\n';
    for (const auto& [name, height] : playerHeights)
        std::cout << std::setw(10) << name << " | " << height << "cm\n";
}

输出:
Insertion of Hinata succeeded
Insertion of Hinata failed
Insertion of Kageyama succeeded
Insertion of Azumane succeeded
Insertion of Hinata failed
Insertion of Tsukishima succeeded
Insertion of Hinata succeeded
Insertion of Hinata succeeded
 
Azumane    | 184.7cm
Hinata     | 162.8cm
Kageyama   | 180.6cm
Kozume     | 169.2cm
Kuroo      | 187.7cm
Tsukishima | 188.3cm

 

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)) 构造被映射值。

#include <iostream>
#include <map>
#include <string>
 
int main()
{
    std::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';
    }
}

a : apple
b : bannana
c : clementine

 

emplace()

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

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

#include <iostream>
#include <utility>
#include <string>
#include <map>
 
int main()
{
    std::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

 

emplace_hint()

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

插入元素到尽可能靠近正好在 hint 之前的位置。原位构造元素,即不进行复制或移动操作。

 

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)...)) 构造元素

注意:不同于 insert 或 emplace ,若不发生插入,则这些函数不从右值参数移动,这令操纵 value 为仅移动类型的 map ,如 std::map<std::string, std::unique_ptr<foo>> 更为容易。另外, try_emplace 分离地处理关键和到 mapped_type 的参数,不同于要求参数构造 value_type (即一个 std::pair )的 emplace 。

#include <iostream>
#include <utility>
#include <string>
 
#include <map>
int main()
{
    using namespace std::literals;
    std::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 );
   iterator erase( 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 的元素(若存在一个),成功返回 1,失败返回 0

常与find() 函数配合使用:

map<int ,string>test;
map<int ,string>::iterator it;
it = test.find(123);
 
if(it == test.end())
    cout << "do not find 123" <<endl;
else  test.erase(it);
#include <map>
#include <iostream>
int main()
{
    std::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( map& other ) noexcept;

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

 

extract()

(1)node_type extract( const_iterator position );   (C++17 起)
(2)node_type extract( const key_type& x );         (C++17 起)

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

(2) 若容器拥有元素而其键等于值 x ,则从容器解链该元素并返回占有它的节点句柄。否则,返回空结点把柄。

任何情况下,均不复制或移动元素,只重指向容器结点的内部指针(可能出现再平衡,和 erase() 一样)。释出结点会非法化指向被释出元素的迭代器。指向被释出元素的指针和引用保持合法,但在结点把柄占有该元素时不能使用:若元素被插入容器,就能使用它们。

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

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

 

merge()

template<class C2>
void merge(std::map<Key, T, C2, Allocator>& source);
template<class C2>
void merge(std::map<Key, T, C2, Allocator>&& source);
template<class C2>
void merge(std::multimap<Key, T, C2, Allocator>& source);
template<class C2>
void merge(std::multimap<Key, T, C2, Allocator>&& source);

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

#include <map>
#include <iostream>
#include <string>
 
int main()
{
  std::map<int, std::string> ma {{1, "apple"}, {5, "pear"}, {10, "banana"}};
  std::map<int, std::string> mb {{2, "zorro"}, {4, "batman"}, {5, "X"}, {8, "alpaca"}};
  std::map<int, std::string> u;
  u.merge(ma);
  std::cout << "ma.size(): " << ma.size() << '\n';
  u.merge(mb);
  std::cout << "mb.size(): " << mb.size() << '\n';
  std::cout << "mb.at(5): " << mb.at(5) << '\n';
  for(auto const &kv: u)
    std::cout << kv.first << ", " << kv.second << '\n';
}

输出:
ma.size(): 0
mb.size(): 1
mb.at(5): X
1, apple
2, zorro
4, batman
5, pear
8, alpaca
10, banana

 

查找

count()

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

返回键 key 的元素数,因为此容器不允许重复,故返回值为 0 或 1。

(1) 返回拥有关键 key 的元素数。

(2) 返回键等于值 x 的元素数。此重载仅若有限定 id Compare::is_transparent 合法且指代一个类型才参与重载决议。这允许调用此函数而不构造 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 的元素。此重载仅若若有限定 id Compare::is_transparent 合法并且指代类型才参与重载决议。允许调用此函数而无需构造 Key 的实例。

find() 函数返回一个指向键为key的元素迭代器,如果没找到返回指向map尾部的迭代器。常用方法如下:

map<int, string>test;
map<int, string>::iterator it;
it = test.find(123);
 
if( it == test.end())
    cout << "do not find 123" <<endl;
else cout << "find 123" <<endl;
#include <iostream>
#include <map>
struct FatKey   { int x; int data[1000]; };
struct LightKey { int x; };
bool operator<(const FatKey& fk, const LightKey& lk) { return fk.x < lk.x; }
bool operator<(const LightKey& lk, const FatKey& fk) { return lk.x < fk.x; }
bool operator<(const FatKey& fk1, const FatKey& fk2) { return fk1.x < fk2.x; }
int main()
{  
// 简单比较演示
    std::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";
    }
 
// 通透比较演示
    std::map<FatKey, char, std::less<>> example2 = { { {1, {} },'a'}, { {2, {} },'b'} };
 
    LightKey lk = {2};
    auto search2 = example2.find(lk);
    if (search2 != example2.end()) {
        std::cout << "Found " << search2->first.x << " " << search2->second << '\n';
    } else {
        std::cout << "Not found\n";
    }
}

输出:
Found 2 b
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 的元素。此重载仅若有限定 id Compare::is_transparent 合法且代表类型才参与重载决议。它允许调用此函数而无需构造 Key 的实例。

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

输出:
Found

 

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;

返回容器中所有拥有给定键的元素范围。范围以两个迭代器定义,一个指向首个不小于 key 的元素,另一个指向首个大于 key 的元素。首个迭代器可以换用 lower_bound() 获得,而第二迭代器可换用 upper_bound() 获得。

(1,2) 比较关键与 key 。

(3,4) 比较关键与值 x 。此重载仅若有限定 id Compare::is_transparent 合法且指代一个类型才参与重载决议。它们允许调用此函数而不构造 Key 的实例。

#include <map>
#include <iostream>
 
int main()
{
    const std::map<int, const char*> m{
        { 0, "zero" },
        { 1, "one" },
        { 2, "two" },
    };
 
    {
        auto p = m.equal_range(1);
        for (auto& q = p.first; q != p.second; ++q) {
            std::cout << "m[" << q->first << "] = " << q->second << '\n';
        }
 
        if (p.second == m.find(2)) {
            std::cout << "end of equal_range (p.second) is one-past p.first\n";
        } else {
            std::cout << "unexpected; p.second expected to be one-past p.first\n";
        }
    }
 
    {
        auto pp = m.equal_range(-1);
        if (pp.first == m.begin()) {
            std::cout << "pp.first is iterator to first not-less than -1\n";
        } else {
            std::cout << "unexpected pp.first\n";
        }
 
        if (pp.second == m.begin()) {
            std::cout << "pp.second is iterator to first element greater-than -1\n";
        } else {
            std::cout << "unexpected pp.second\n";
        }
    }
 
    {
        auto ppp = m.equal_range(3);
        if (ppp.first == m.end()) {
            std::cout << "ppp.first is iterator to first not-less than 3\n";
        } else {
            std::cout << "unexpected ppp.first\n";
        }
 
        if (ppp.second == m.end()) {
            std::cout << "ppp.second is iterator to first element greater-than 3\n";
        } else {
            std::cout << "unexpected ppp.second\n";
        }
    }
}

输出:
m[1] = one
end of equal_range (p.second) is one-past p.first
pp.first is iterator to first not-less than -1
pp.second is iterator to first element greater-than -1
ppp.first is iterator to first not-less than 3
ppp.second is iterator to first element greater-than 3

 

lower_bound()

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

(1) 返回首个不小于 key 的元素的迭代器。
(2) 返回首个不小于值 x 的元素的迭代器。此重载仅若有限定 id Compare::is_transparent 合法并指代一个类型才参与重载决议。它们允许调用此函数而无需构造 Key 的实例。

 

upper_bound()

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

(1) 返回指向首个大于 key 的元素的迭代器。

(2) 返回指向首个大于值 x 的元素的迭代器。此重载仅若有限定 id Compare::is_transparent 合法并指代一个类型才参与重载决议。这允许调用此函数而无需构造 Key 的实例。

 

std::swap(std::map)

emplate< class Key, class T, class Compare, class Alloc >
void swap( map<Key,T,Compare,Alloc>& lhs, 
           map<Key,T,Compare,Alloc>& rhs ) noexcept(/* see below */);

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

 

std::erase_if (std::map)

template< class Key, class T, class Compare, class Alloc, class Pred >
typename std::map<Key,T,Compare,Alloc>::size_type
    erase_if(std::map<Key,T,Compare,Alloc>& c, Pred pred);

从容器中除所有满足谓词 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();
#include <iostream>
#include <map>
 
auto show = [](const auto& map) {
    std::cout << "map[" << map.size() << "] { ";
    for (auto const& item : map) {
        std::cout << "{ " << item.first << ", " << item.second << " } ";
    }
    std::cout << "}\n\n";
};
 
auto main() -> int
{
    std::cout << "Initial map<int, char>:" "\n";
    std::map<int, char> map { { 1, 'a' }, { 2, 'b' }, { 3, 'c' }, { 4, 'd' }, { 5, 'e' } };
    show(map);
 
    std::cout << "Remove items with odd keys:" "\n";
    const auto count = std::erase_if(map, [](const auto& item) {
        auto const& [key, value] = item;
        return (key & 1) == 1;
    });
    show(map);
 
    std::cout << count << " items where removed.\n";
}

输出:
Initial map<int, char>:
map[5] { { 1, a } { 2, b } { 3, c } { 4, d } { 5, e } }
 
Remove items with odd keys:
map[2] { { 2, b } { 4, d } }
 
3 items where removed.

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐