C++ map 使用詳解(含C++20新特性)

目錄

訪問元素

迭代器

容量

修改操作

查找

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.

 

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