目录

访问元素

迭代器

容量

修改操作

查找

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 valueletter_counts['x'] = 9;  // insert a new valuestd::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);}// 打印结果 mapstd::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 succeededAzumane    | 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_typeerase_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.

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

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

    目录 查找元素 迭代器 容量 修改操作 通接口 哈希策略 观察器 std::swap(std::unordered_map) std::erase_if (std::unordered_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. 万字详解,JDK1.8新特性的Lambda、Stream和日期的使用详解

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

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

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

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

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

  8. jQuery数组处理详解(含实例演示)

    jQuery的数组处理,便捷,功能齐全. 最近的项目中用到的比较多,深感实用,一步到位的封装了很多原生js数组不能企及的功能. 最近时间紧迫,今天抽了些时间回过头来看 jQuery中文文档 中对数组的 ...

  9. pythonpandas函数详解_对pandas中Series的map函数详解

    Series的map方法可以接受一个函数或含有映射关系的字典型对象. 使用map是一种实现元素级转换以及其他数据清理工作的便捷方式. (DataFrame中对应的是applymap()函数,当然Dat ...

最新文章

  1. tidb mysql 协议_TiDB源码阅读(二) TiDB中的MySQL协议
  2. web开发快速提高工作效率的一些资源
  3. AI:2020 科大讯飞AI开发者大赛,总奖金池180+万元!拿下比赛,大厂offer到手,那么,你还在等什么?
  4. 一个9年的技术最近一直担心找不到工作
  5. ppt拖动就复制_学会这3个PPT技巧和29个快捷键!让你的PPT脱颖而出,领导叫好
  6. python报错:TypeError: 'str' object is not callable
  7. 快速弄懂陌生领域是一项“赚钱”的能力
  8. 数据库查询经常卡死?面对亿级大数据量,我是这么展示分析的
  9. 餐饮店楼梯空间的设计方案
  10. 基于React的PC网站前端架构分析
  11. SOLO参赛,赛道二周冠军“达尔文”分享上分秘诀
  12. java频繁查询数据库_如何解决Cookie登录 频繁查询数据库问题?
  13. 12.Flask-Restful
  14. [Oracle]Oracle表权限小结
  15. java是学习方程!
  16. 【原型】Axure基本入门
  17. win7安装JAVA程序闪退怎么办_win7打开软件闪退如何解决
  18. CSDN怎么改变字体颜色
  19. ElasticSearch封装查询、多条件查询、模糊查询工具类
  20. 《Universal Language Model Fine-tuning for Text Classification》翻译

热门文章

  1. Shell简介:什么是Shell,Shell命令的两种执行方式
  2. 高级数据结构与算法 | LFU缓存机制(Least Frequently Used)
  3. 设计模式--装饰模式
  4. 如何使用 Kafka、MongoDB 和 Maxwell’s Daemon 构建 SQL 数据库的审计系统
  5. 5分钟了解CDN 加速原理 | +新书推荐
  6. Hadoop之HDFS面试知识复习
  7. 程序员下班后收到工作信息怎么办?
  8. 如何设计一个 A/B test?
  9. Anaconda 安装 Tensorflow 教程
  10. CentOS7系统上Kubernetes集群搭建