科技改變生活 · 科技引領未來

              • 首頁
              • 資訊
              • 技術
              • 百科
              • 問答
              • 學習
              • 看看
              • 站長
              • 生活
              • 快訊

              首頁 > 看看 > 創業經驗

              un是什么意思 un代表愛情

              時間:2022-08-25 11:52 作者:高悅明

              C++ STL無序容器(哈希容器)是什么?

              繼 map、multimap、set、multiset 關聯式容器之后,從本節開始,再講解一類“特殊”的關聯式容器,它們常被稱為“無序容器”、“哈希容器”或者“無序關聯容器”。

              和關聯式容器一樣,無序容器也使用鍵值對(pair 類型)的方式存儲數據。不過,本教程將二者分開進行講解,因為它們有本質上的不同:

              • 關聯式容器的底層實現采用的樹存儲結構,更確切的說是紅黑樹結構;
              • 無序容器的底層實現采用的是哈希表的存儲結構。

              C++ STL 底層采用哈希表實現無序容器時,會將所有數據存儲到一整塊連續的內存空間中,并且當數據存儲位置發生沖突時,解決方法選用的是“鏈地址法”(又稱“開鏈法”)。有關哈希表存儲結構,讀者可閱讀《哈希表(散列表)詳解》一文做詳細了解。

              基于底層實現采用了不同的數據結構,因此和關聯式容器相比,無序容器具有以下 2 個特點:

              1. 無序容器內部存儲的鍵值對是無序的,各鍵值對的存儲位置取決于該鍵值對中的鍵,
              2. 和關聯式容器相比,無序容器擅長通過指定鍵查找對應的值(平均時間復雜度為 O(1));但對于使用迭代器遍歷容器中存儲的元素,無序容器的執行效率則不如關聯式容器。

              C++ STL無序容器種類

              和關聯式容器一樣,無序容器只是一類容器的統稱,其包含有 4 個具體容器,分別為 unordered_map、unordered_multimap、unordered_set 以及 unordered_multiset。

              表 1 對這 4 種無序容器的功能做了詳細的介紹。

              可能讀者已經發現,以上 4 種無序容器的名稱,僅是在前面所學的 4 種關聯式容器名稱的基礎上,添加了 &34;unordered_&34;。如果讀者已經學完了 map、multimap、set 和 multiset 容器不難發現,以 map 和 unordered_map 為例,其實它們僅有一個區別,即 map 容器內存會對存儲的鍵值對進行排序,而 unordered_map 不會。

              也就是說,C++ 11 標準的 STL 中,在已提供有 4 種關聯式容器的基礎上,又新增了各自的“unordered”版本(無序版本、哈希版本),提高了查找指定元素的效率。

              有讀者可能會問,既然無序容器和之前所學的關聯式容器類似,那么在實際使用中應該選哪種容器呢?總的來說,實際場景中如果涉及大量遍歷容器的操作,建議首選關聯式容器;反之,如果更多的操作是通過鍵獲取對應的值,則應首選無序容器。

              為了加深讀者對無序容器的認識,這里以 unordered_map 容器為例,舉個例子(不必深究該容器的具體用法):

              include 
              include 
              include 
              using namespace std;
              
              int main()
              {
              //創建并初始化一個 unordered_map 容器,其存儲的  類型的鍵值對
              std::unordered_map my_uMap{
              {&34;C語言教程&34;,&34;http://c.biancheng.net/c/&34;},
              {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
              {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;} };
              //查找指定鍵對應的值,效率比關聯式容器高
              string str = my_uMap.at(&34;C語言教程&34;);
              cout << &34;str = &34; << str << endl;
              
              //使用迭代器遍歷哈希容器,效率不如關聯式容器
              for (auto iter = my_uMap.begin(); iter != my_uMap.end(); ++iter)
              {
              //pair 類型鍵值對分為 2 部分
              cout << iter->first << &34; &34; << iter->second << endl;
              }
              return 0;
              }

              程序執行結果為:

              str = http://c.biancheng.net/c/

              C語言教程 http://c.biancheng.net/c/

              Python教程 http://c.biancheng.net/python/

              Java教程 http://c.biancheng.net/java/

              C++ STL unordered_map容器用法詳解

              C++ STL 標準庫中提供有 4 種無序關聯式容器,本節先講解 unordered_map 容器。

              unordered_map 容器,直譯過來就是&34;無序 map 容器&34;的意思。所謂“無序”,指的是 unordered_map 容器不會像 map 容器那樣對存儲的數據進行排序。換句話說,unordered_map 容器和 map 容器僅有一點不同,即 map 容器中存儲的數據是有序的,而 unordered_map 容器中是無序的。

              對于已經學過 map 容器的讀者,可以將 unordered_map 容器等價為無序的 map 容器。

              具體來講,unordered_map 容器和 map 容器一樣,以鍵值對(pair類型)的形式存儲數據,存儲的各個鍵值對的鍵互不相同且不允許被修改。但由于 unordered_map 容器底層采用的是哈希表存儲結構,該結構本身不具有對數據的排序功能,所以此容器內部不會自行對存儲的鍵值對進行排序。

              值得一提的是,unordered_map 容器在頭文件中,并位于 std 命名空間中。因此,如果想使用該容器,代碼中應包含如下語句:

              include using namespace std;

              注意,第二行代碼不是必需的,但如果不用,則后續程序中在使用此容器時,需手動注明 std 命名空間(強烈建議初學者使用)。

              unordered_map 容器模板的定義如下所示:

              template < class Key,                        //鍵值對中鍵的類型          
                class T,                          //鍵值對中值的類型           
                  class Hash = hash,           //容器內部存儲鍵值對所用的哈希函數           
                    class Pred = equal_to,       //判斷各個鍵值對鍵相同的規則           
                      class Alloc = allocator< pairnst Key,T> >  // 指定分配器對象的類型          
                        > class unordered_map;

              以上 5 個參數中,必須顯式給前 2 個參數傳值,并且除特殊情況外,最多只需要使用前 4 個參數,各自的含義和功能如表 1 所示。

              表 1 unordered_map 容器模板類的常用參數

              總的來說,當無序容器中存儲鍵值對的鍵為自定義類型時,默認的哈希函數 hash 以及比較函數 equal_to 將不再適用,只能自己設計適用該類型的哈希函數和比較函數,并顯式傳遞給 Hash 參數和 Pred 參數。至于如何實現自定義,后續章節會做詳細講解。

              創建C++ unordered_map容器的方法

              常見的創建 unordered_map 容器的方法有以下幾種。

              1) 通過調用 unordered_map 模板類的默認構造函數,可以創建空的 unordered_map 容器。比如:

              std::unordered_map umap;

              由此,就創建好了一個可存儲 類型鍵值對的 unordered_map 容器。

              2) 當然,在創建 unordered_map 容器的同時,可以完成初始化操作。比如:

              std::unordered_map umap{    
                {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},    
                  {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},    
                    {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };

              通過此方法創建的 umap 容器中,就包含有 3 個鍵值對元素。

              3) 另外,還可以調用 unordered_map 模板中提供的復制(拷貝)構造函數,將現有 unordered_map 容器中存儲的鍵值對,復制給新建 unordered_map 容器。

              例如,在第二種方式創建好 umap 容器的基礎上,再創建并初始化一個 umap2 容器:

              std::unordered_map umap2(umap);

              由此,umap2 容器中就包含有 umap 容器中所有的鍵值對。

              除此之外,C++ 11 標準中還向 unordered_map 模板類增加了移動構造函數,即以右值引用的方式將臨時 unordered_map 容器中存儲的所有鍵值對,全部復制給新建容器。例如:

              //返回臨時 unordered_map 容器的函數
              std::unordered_map  retUmap(){    
                std::unordered_maptempUmap{      
                  {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},       
                    {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},       
                      {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };    
                return tempUmap;}
              //調用移動構造函數,創建 umap2 容器
              std::unordered_map umap2(retUmap());

              注意,無論是調用復制構造函數還是拷貝構造函數,必須保證 2 個容器的類型完全相同。

              4) 當然,如果不想全部拷貝,可以使用 unordered_map 類模板提供的迭代器,在現有 unordered_map 容器中選擇部分區域內的鍵值對,為新建 unordered_map 容器初始化。例如:

              //傳入 2 個迭代器,
              std::unordered_map 
                umap2(++umap.begin(),umap.end());

              通過此方式創建的 umap2 容器,其內部就包含 umap 容器中除第 1 個鍵值對外的所有其它鍵值對。

              C++ unordered_map容器的成員方法

              unordered_map 既可以看做是關聯式容器,更屬于自成一脈的無序容器。因此在該容器模板類中,既包含一些在學習關聯式容器時常見的成員方法,還有一些屬于無序容器特有的成員方法。

              表 2 列出了 unordered_map 類模板提供的所有常用的成員方法以及各自的功能。

              注意,對于實現互換 2 個相同類型 unordered_map 容器的鍵值對,除了可以調用該容器模板類中提供的 swap() 成員方法外,STL 標準庫還提供了同名的 swap() 非成員函數。

              下面的樣例演示了表 2 中部分成員方法的用法:

              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建空 umap 容器
              unordered_map umap;
              //向 umap 容器添加新鍵值對
              umap.emplace(&34;Python教程&34;, &34;http://c.biancheng.net/python/&34;);
              umap.emplace(&34;Java教程&34;, &34;http://c.biancheng.net/java/&34;);
              umap.emplace(&34;Linux教程&34;, &34;http://c.biancheng.net/linux/&34;);
              
              //輸出 umap 存儲鍵值對的數量
              cout << &34;umap size = &34; << umap.size() << endl;
              //使用迭代器輸出 umap 容器存儲的所有鍵值對
              for (auto iter = umap.begin(); iter != umap.end(); ++iter) {
              cout << iter->first << &34; &34; << iter->second << endl;
              }
              return 0;
              }

              程序執行結果為:

              umap size = 3

              Python教程 http://c.biancheng.net/python/

              Linux教程 http://c.biancheng.net/linux/

              Java教程 http://c.biancheng.net/java/

              C++ STL無序容器底層實現原理(深度剖析)

              在了解哈希表存儲結構的基礎上,本節將具體分析 C++ STL 無序容器(哈希容器)底層的實現原理。

              C++ STL 標準庫中,不僅是 unordered_map 容器,所有無序容器的底層實現都采用的是哈希表存儲結構。更準確地說,是用“鏈地址法”(又稱“開鏈法”)解決數據存儲位置發生沖突的哈希表,整個存儲結構如圖 1 所示。

              其中,Pi 表示存儲的各個鍵值對。

              可以看到,當使用無序容器存儲鍵值對時,會先申請一整塊連續的存儲空間,但此空間并不用來直接存儲鍵值對,而是存儲各個鏈表的頭指針,各鍵值對真正的存儲位置是各個鏈表的節點。

              注意,STL 標準庫通常選用 vector 容器存儲各個鏈表的頭指針。

              不僅如此,在 C++ STL 標準庫中,將圖 1 中的各個鏈表稱為桶(bucket),每個桶都有自己的編號(從 0 開始)。當有新鍵值對存儲到無序容器中時,整個存儲過程分為如下幾步:

              1. 將該鍵值對中鍵的值帶入設計好的哈希函數,會得到一個哈希值(一個整數,用 H 表示);
              2. 將 H 和無序容器擁有桶的數量 n 做整除運算(即 H % n),該結果即表示應將此鍵值對存儲到的桶的編號;
              3. 建立一個新節點存儲此鍵值對,同時將該節點鏈接到相應編號的桶上。

              另外值得一提的是,哈希表存儲結構還有一個重要的屬性,稱為負載因子(load factor)。該屬性同樣適用于無序容器,用于衡量容器存儲鍵值對的空/滿程序,即負載因子越大,意味著容器越滿,即各鏈表中掛載著越多的鍵值對,這無疑會降低容器查找目標鍵值對的效率;反之,負載因子越小,容器肯定越空,但并不一定各個鏈表中掛載的鍵值對就越少。

              舉個例子,如果設計的哈希函數不合理,使得各個鍵值對的鍵帶入該函數得到的哈希值始終相同(所有鍵值對始終存儲在同一鏈表上)。這種情況下,即便增加桶數是的負載因子減小,該容器的查找效率依舊很差。

              無序容器中,負載因子的計算方法為:

              負載因子 = 容器存儲的總鍵值對 / 桶數

              默認情況下,無序容器的最大負載因子為 1.0。如果操作無序容器過程中,使得最大復雜因子超過了默認值,則容器會自動增加桶數,并重新進行哈希,以此來減小負載因子的值。需要注意的是,此過程會導致容器迭代器失效,但指向單個鍵值對的引用或者指針仍然有效。

              這也就解釋了,為什么我們在操作無序容器過程中,鍵值對的存儲順序有時會“莫名”的發生變動。

              C++ STL 標準庫為了方便用戶更好地管控無序容器底層使用的哈希表存儲結構,各個無序容器的模板類中都提供表 2 所示的成員方法。

              表 2 無序容器管理哈希表的成員方法

              下面的程序以學過的 unordered_map 容器為例,演示了表 2 中部分成員方法的用法:

              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建空 umap 容器
              unordered_map umap;
              
              cout << &34;umap 初始桶數: &34; << umap.bucket_count() << endl;
              cout << &34;umap 初始負載因子: &34; << umap.load_factor() << endl;
              cout << &34;umap 最大負載因子: &34; << umap.max_load_factor() << endl;
              
              //設置 umap 使用最適合存儲 9 個鍵值對的桶數
              umap.reserve(9);
              cout << &34;*********************&34; << endl;
              cout << &34;umap 新桶數: &34; << umap.bucket_count() << endl;
              cout << &34;umap 新負載因子: &34; << umap.load_factor() << endl;
              //向 umap 容器添加 3 個鍵值對
              umap[&34;Python教程&34;] = &34;http://c.biancheng.net/python/&34;;
              umap[&34;Java教程&34;] = &34;http://c.biancheng.net/java/&34;;
              umap[&34;Linux教程&34;] = &34;http://c.biancheng.net/linux/&34;;
              //調用 bucket() 獲取指定鍵值對位于桶的編號
              cout << &34;以&34;Python教程&34;為鍵的鍵值對,位于桶的編號為:&34; << umap.bucket(&34;Python教程&34;) << endl;
              //自行計算某鍵值對位于哪個桶
              auto fn = umap.hash_function();
              cout << &34;計算以&34;Python教程&34;為鍵的鍵值對,位于桶的編號為:&34; << fn(&34;Python教程&34;) % (umap.bucket_count()) << endl;
              return 0;
              }

              程序執行結果為:

              umap 初始桶數: 8

              umap 初始負載因子: 0

              umap 最大負載因子: 1

              *********************

              umap 新桶數: 16

              umap 新負載因子: 0

              以&34;Python教程&34;為鍵的鍵值對,位于桶的編號為:9

              計算以&34;Python教程&34;為鍵的鍵值對,位于桶的編號為:9

              從輸出結果可以看出,對于空的 umap 容器,初始狀態下會分配 8 個桶,并且默認最大負載因子為 1.0,但由于其為存儲任何鍵值對,因此負載因子值為 0。

              與此同時,程序中調用 reverse() 成員方法,是 umap 容器的桶數改為了 16,其最適合存儲 9 個鍵值對。從側面可以看出,一旦負載因子大于 1.0(9/8 > 1.0),則容器所使用的桶數就會翻倍式(8、16、32、...)的增加。

              程序最后還演示了如何手動計算出指定鍵值對存儲的桶的編號,其計算結果和使用 bucket() 成員方法得到的結果是一致的。

              C++ unordered_map迭代器的用法

              C++ STL 標準庫中,unordered_map 容器迭代器的類型為前向迭代器(又稱正向迭代器)。這意味著,假設 p 是一個前向迭代器,則其只能進行 *p、p++、++p 操作,且 2 個前向迭代器之間只能用 == 和 != 運算符做比較。

              在 unordered_map 容器模板中,提供了表 1 所示的成員方法,可用來獲取指向指定位置的前向迭代器。

              表 1 C++ unordered_map迭代器相關成員方法

              值得一提的是,equal_range(key) 很少用于 unordered_map 容器,因為該容器中存儲的都是鍵不相等的鍵值對,即便調用該成員方法,得到的 2 個迭代器所表示的范圍中,最多只包含 1 個鍵值對。事實上,該成員方法更適用于 unordered_multimap 容器(該容器后續章節會做詳細講解)。

              下面的程序演示了表 1 中部分成員方法的用法。

              include 
              include 
              include 
              using namespace std;
              int main()
              {
                  //創建 umap 容器
                  unordered_map umap{
                      {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
                      {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},
                      {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };
                  cout << &34;umap 存儲的鍵值對包括:&34; << endl;
                  //遍歷輸出 umap 容器中所有的鍵值對
                  for (auto iter = umap.begin(); iter != umap.end(); ++iter) {
                      cout << &34;<&34; << iter->first << &34;, &34; << iter->second << &34;>&34; << endl;
                  }
                  //獲取指向指定鍵值對的前向迭代器
                  unordered_map::iterator iter = umap.find(&34;Java教程&34;);
                  cout <<&34;umap.find(&34;Java教程&34;) = &34; << &34;<&34; << iter->first << &34;, &34; << iter->second << &34;>&34; << endl;
                  return 0;
              }

              程序執行結果為:

              umap 存儲的鍵值對包括:

              umap.find(&34;Java教程&34;) =

              需要注意的是,在操作 unordered_map 容器過程(尤其是向容器中添加新鍵值對)中,一旦當前容器的負載因子超過最大負載因子(默認值為 1.0),該容器就會適當增加桶的數量(通常是翻一倍),并自動執行 rehash() 成員方法,重新調整各個鍵值對的存儲位置(此過程又稱“重哈希”),此過程很可能導致之前創建的迭代器失效。

              所謂迭代器失效,針對的是那些用于表示容器內某個范圍的迭代器,由于重哈希會重新調整每個鍵值對的存儲位置,所以容器重哈希之后,之前表示特定范圍的迭代器很可能無法再正確表示該范圍。但是,重哈希并不會影響那些指向單個鍵值對元素的迭代器。

              舉個例子:

              include 
              include 
              using namespace std;
              int main()
              {
              //創建 umap 容器
              unordered_map umap;
              //向 umap 容器添加 50 個鍵值對
              for (int i = 1; i <= 50; i++) {
              umap.emplace(i, i);
              }
              //獲取鍵為 49 的鍵值對所在的范圍
              auto pair = umap.equal_range(49);
              //輸出 pair 范圍內的每個鍵值對的鍵的值
              for (auto iter = pair.first; iter != pair.second; ++iter) {
              cout << iter->first <<&34; &34;;
              }
              cout << endl;
              //手動調整最大負載因子數
              umap.max_load_factor(3.0);
              //手動調用 rehash() 函數重哈希
              umap.rehash(10);
              //重哈希之后,pair 的范圍可能會發生變化
              for (auto iter = pair.first; iter != pair.second; ++iter) {
              cout << iter->first << &34; &34;;
              }
              return 0;
              }

              程序執行結果為:

              49

              49 17

              觀察輸出結果不難發現,之前用于表示鍵為 49 的鍵值對所在范圍的 2 個迭代器,重哈希之后表示的范圍發生了改變。

              經測試,用于遍歷整個容器的 begin()/end() 和 cbegin()/cend() 迭代器對,重哈希只會影響遍歷容器內鍵值對的順序,整個遍歷的操作仍然可以順利完成。

              C++ STL unordered_map獲取元素的4種方法(超級詳細)

              通過前面的學習我們知道,unordered_map 容器以鍵值對的方式存儲數據。為了方便用戶快速地從該類型容器提取出目標元素(也就是某個鍵值對的值),unordered_map 容器類模板中提供了以下幾種方法。

              1) unordered_map 容器類模板中,實現了對 [ ] 運算符的重載,使得我們可以像“利用下標訪問普通數組中元素”那樣,通過目標鍵值對的鍵獲取到該鍵對應的值。

              舉個例子:

              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建 umap 容器
              unordered_map umap{
              {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
              {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},
              {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };
              //獲取 &34;Java教程&34; 對應的值
              string str = umap[&34;Java教程&34;];
              cout << str << endl;
              return 0;
              }

              程序輸出結果為:

              http://c.biancheng.net/java/

              需要注意的是,如果當前容器中并沒有存儲以 [ ] 運算符內指定的元素作為鍵的鍵值對,則此時 [ ] 運算符的功能將轉變為:向當前容器中添加以目標元素為鍵的鍵值對。舉個例子:

              include 
              include 
              include 
              using namespace std;
              int main()
              {
                  //創建空 umap 容器
                  unordered_map umap;
                  //[] 運算符在 = 右側
                  string str = umap[&34;STL教程&34;];
                  //[] 運算符在 = 左側
                  umap[&34;C教程&34;] = &34;http://c.biancheng.net/c/&34;;
                 
                  for (auto iter = umap.begin(); iter != umap.end(); ++iter) {
                      cout << iter->first << &34; &34; << iter->second << endl;
                  }
                  return 0;
              }

              程序執行結果為:

              C教程 http://c.biancheng.net/c/

              STL教程

              可以看到,當使用 [ ] 運算符向 unordered_map 容器中添加鍵值對時,分為 2 種情況:

              1. 當 [ ] 運算符位于賦值號(=)右側時,則新添加鍵值對的鍵為 [ ] 運算符內的元素,其值為鍵值對要求的值類型的默認值(string 類型默認值為空字符串);
              2. 當 [ ] 運算符位于賦值號(=)左側時,則新添加鍵值對的鍵為 [ ] 運算符內的元素,其值為賦值號右側的元素。

              2) unordered_map 類模板中,還提供有 at() 成員方法,和使用 [ ] 運算符一樣,at() 成員方法也需要根據指定的鍵,才能從容器中找到該鍵對應的值;不同之處在于,如果在當前容器中查找失敗,該方法不會向容器中添加新的鍵值對,而是直接拋出out_of_range異常。

              舉個例子:

              include 
                include 
                include 
                using namespace std;
              int main(){    
                //創建 umap 容器   
                unordered_map umap{       
                  {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},       
                    {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},        
                      {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };   
                //獲取指定鍵對應的值    
                string str = umap.at(&34;Python教程&34;);    
                cout << str << endl;    
                //執行此語句會拋出 out_of_range 異常  
                //cout << umap.at(&34;GO教程&34;);    
                return 0;}

              程序執行結果為:

              http://c.biancheng.net/python/

              此程序中,第 13 行代碼用于獲取 umap 容器中鍵為“Python教程”對應的值,由于 umap 容器確實有符合條件的鍵值對,因此可以成功執行;而第 17 行代碼,由于當前 umap 容器沒有存儲以“Go教程”為鍵的鍵值對,因此執行此語句會拋出 out_of_range 異常。

              3) [ ] 運算符和 at() 成員方法基本能滿足大多數場景的需要。除此之外,還可以借助 unordered_map 模板中提供的 find() 成員方法。

              和前面方法不同的是,通過 find() 方法得到的是一個正向迭代器,該迭代器的指向分以下 2 種情況:

              1. 當 find() 方法成功找到以指定元素作為鍵的鍵值對時,其返回的迭代器就指向該鍵值對;
              2. 當 find() 方法查找失敗時,其返回的迭代器和 end() 方法返回的迭代器一樣,指向容器中最后一個鍵值對之后的位置。

              舉個例子:

              include 
                include 
                include 
                using namespace std;
              int main(){    
                //創建 umap 容器   
                unordered_map umap{        
                  {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},        
                    {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},        
                      {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };    
                //查找成功    
                unordered_map::iterator iter = umap.find(&34;Python教程&34;);   
                cout << iter->first << &34; &34; << iter->second << endl;  
                //查找失敗    
                unordered_map::iterator iter2 = umap.find(&34;GO教程&34;);   
                if (iter2 == umap.end()) {       
                  cout << &34;當前容器中沒有以&34;GO教程&34;為鍵的鍵值對&34;;    
                }   
                return 0;}

              程序執行結果為:

              Python教程 http://c.biancheng.net/python/

              當前容器中沒有以&34;GO教程&34;為鍵的鍵值對

              4) 除了 find() 成員方法之外,甚至可以借助 begin()/end() 或者 cbegin()/cend(),通過遍歷整個容器中的鍵值對來找到目標鍵值對。

              舉個例子:

              include 
              include 
              include 
              using namespace std;
              int main()
              {
                  //創建 umap 容器
                  unordered_map umap{
                      {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
                      {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;},
                      {&34;Linux教程&34;,&34;http://c.biancheng.net/linux/&34;} };
                  //遍歷整個容器中存儲的鍵值對
                  for (auto iter = umap.begin(); iter != umap.end(); ++iter) {
                      //判斷當前的鍵值對是否就是要找的
                      if (!iter->first.compare(&34;Java教程&34;)) {
                          cout << iter->second << endl;
                          break;
                      }
                  }
                  return 0;
              }

              程序執行結果為:

              http://c.biancheng.net/java/

              以上 4 種方法中,前 2 種方法基本能滿足多數場景的需要,建議初學者首選 at() 成員方法!

              C++ unordered_map insert()用法

              為了方便用戶向已建 unordered_map 容器中添加新的鍵值對,該容器模板中提供了 insert() 方法,本節就對此方法的用法做詳細的講解。

              unordered_map 模板類中,提供了多種語法格式的 insert() 方法,根據功能的不同,可劃分為以下幾種用法。

              1) insert() 方法可以將 pair 類型的鍵值對元素添加到 unordered_map 容器中,其語法格式有 2 種:

              //以普通方式傳遞參數

              pair insert ( const value_type& val );

              //以右值引用的方式傳遞參數

              template

              pair insert ( P&& val );

              為了方便用戶向已建 unordered_map 容器中添加新的鍵值對,該容器模板中提供了 insert() 方法,本節就對此方法的用法做詳細的講解。

              unordered_map 模板類中,提供了多種語法格式的 insert() 方法,根據功能的不同,可劃分為以下幾種用法。

              1) insert() 方法可以將 pair 類型的鍵值對元素添加到 unordered_map 容器中,其語法格式有 2 種:

              //以普通方式傳遞參數

              pair insert ( const value_type& val );

              //以右值引用的方式傳遞參數

              template

              pair insert ( P&& val );

              以上 2 種格式中,參數 val 表示要添加到容器中的目標鍵值對元素;該方法的返回值為 pair類型值,內部包含一個 iterator 迭代器和 bool 變量:

              • 當 insert() 將 val 成功添加到容器中時,返回的迭代器指向新添加的鍵值對,bool 值為 True;
              • 當 insert() 添加鍵值對失敗時,意味著當前容器中本就存儲有和要添加鍵值對的鍵相等的鍵值對,這種情況下,返回的迭代器將指向這個導致插入操作失敗的迭代器,bool 值為 False。
              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建空 umap 容器
              unordered_map umap;
              //構建要添加的鍵值對
              std::pairmypair(&34;STL教程&34;, &34;http://c.biancheng.net/stl/&34;);
              //創建接收 insert() 方法返回值的pair類型變量
              std::pair::iterator, bool> ret;
              //調用 insert() 方法的第一種語法格式
              ret = umap.insert(mypair);
              cout << &34;bool = &34; << ret.second << endl;
              cout << &34;iter -> &34; << ret.first->first <<&34; &34; << ret.first->second << endl;
              
              //調用 insert() 方法的第二種語法格式
              ret = umap.insert(std::make_pair(&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;));
              cout << &34;bool = &34; << ret.second << endl;
              cout << &34;iter -> &34; << ret.first->first << &34; &34; << ret.first->second << endl;
              return 0;
              }
              

              程序執行結果為:

              bool = 1

              iter -> STL教程 http://c.biancheng.net/stl/

              bool = 1

              iter -> Python教程 http://c.biancheng.net/python/

              從輸出結果很容易看出,兩次添加鍵值對的操作,insert() 方法返回值中的 bool 變量都為 1,表示添加成功,此時返回的迭代器指向的是添加成功的鍵值對。

              2) 除此之外,insert() 方法還可以指定新鍵值對要添加到容器中的位置,其語法格式如下:

              //以普通方式傳遞 val 參數

              iterator insert ( const_iterator hint, const value_type& val );

              //以右值引用方法傳遞 val 參數

              template

              iterator insert ( const_iterator hint, P&& val );

              以上 2 種語法格式中,hint 參數為迭代器,用于指定新鍵值對要添加到容器中的位置;val 參數指的是要添加容器中的鍵值對;方法的返回值為迭代器:

              • 如果 insert() 方法成功添加鍵值對,該迭代器指向新添加的鍵值對;
              • 如果 insert() 方法添加鍵值對失敗,則表示容器中本就包含有相同鍵的鍵值對,該方法返回的迭代器就指向容器中鍵相同的鍵值對;

              注意,以上 2 種語法格式中,雖然通過 hint 參數指定了新鍵值對添加到容器中的位置,但該鍵值對真正存儲的位置,并不是 hint 參數說了算,最終的存儲位置仍取決于該鍵值對的鍵的值。

              include 
              include 
              include 
              using namespace std;
              int main()
              {
                  //創建空 umap 容器
                  unordered_map umap;
                  //構建要添加的鍵值對
                  std::pairmypair(&34;STL教程&34;, &34;http://c.biancheng.net/stl/&34;);
                  //創建接收 insert() 方法返回值的迭代器類型變量
                  unordered_map::iterator iter;
                  //調用第一種語法格式
                  iter = umap.insert(umap.begin(), mypair);
                  cout << &34;iter -> &34; << iter->first <<&34; &34; << iter->second << endl;
                 
                  //調用第二種語法格式
                  iter = umap.insert(umap.begin(),std::make_pair(&34;Python教程&34;, &34;http://c.biancheng.net/python/&34;));
                  cout << &34;iter -> &34; << iter->first << &34; &34; << iter->second << endl;
                  return 0;
              }

              程序輸出結果為:

              iter -> STL教程 http://c.biancheng.net/stl/

              iter -> Python教程 http://c.biancheng.net/python/

              3) insert() 方法還支持將某一個 unordered_map 容器中指定區域內的所有鍵值對,復制到另一個 unordered_map 容器中,其語法格式如下:

              template

              void insert ( InputIterator first, InputIterator last );

              其中 first 和 last 都為迭代器,[first, last)表示復制其它 unordered_map 容器中鍵值對的區域。

              include 
              include 
              include 
              using namespace std;
              int main()
              {
                  //創建并初始化 umap 容器
                  unordered_map umap{ {&34;STL教程&34;,&34;http://c.biancheng.net/stl/&34;},
                  {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
                  {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;} };
                  //創建一個空的 unordered_map 容器
                  unordered_map otherumap;
                  //指定要拷貝 umap 容器中鍵值對的范圍
                  unordered_map::iterator first = ++umap.begin();
                  unordered_map::iterator last = umap.end();
                  //將指定 umap 容器中 [first,last) 區域內的鍵值對復制給 otherumap 容器
                  otherumap.insert(first, last);
                  //遍歷 otherumap 容器中存儲的鍵值對
                  for (auto iter = otherumap.begin(); iter != otherumap.end(); ++iter){
                      cout << iter->first << &34; &34; << iter->second << endl;
                  }
                  return 0;
              }

              程序輸出結果為:

              Python教程 http://c.biancheng.net/python/

              Java教程 http://c.biancheng.net/java/

              4) 除了以上 3 種方式,insert() 方法還支持一次向 unordered_map 容器添加多個鍵值對,其語法格式如下:

              void insert ( initializer_list il );

              其中,il 參數指的是可以用初始化列表的形式指定多個鍵值對元素。

              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建空的 umap 容器
              unordered_map umap;
              
              //向 umap 容器同時添加多個鍵值對
              umap.insert({ {&34;STL教程&34;,&34;http://c.biancheng.net/stl/&34;},
              {&34;Python教程&34;,&34;http://c.biancheng.net/python/&34;},
              {&34;Java教程&34;,&34;http://c.biancheng.net/java/&34;} });
              //遍歷輸出 umap 容器中存儲的鍵值對
              for (auto iter = umap.begin(); iter != umap.end(); ++iter){
              cout << iter->first << &34; &34; << iter->second << endl;
              }
              return 0;
              }

              程序輸出結果為:

              STL教程 http://c.biancheng.net/stl/

              Python教程 http://c.biancheng.net/python/

              Java教程 http://c.biancheng.net/java/

              C++ unordered_map emplace()和emplace_hint()方法

              和前面學的 map、set 等容器一樣,C++ 11 標準也為 unordered_map 容器新增了 emplace() 和 emplace_hint() 成員方法,本節將對它們的用法做詳細的介紹。

              我們知道,實現向已有 unordered_map 容器中添加新鍵值對,可以通過調用 insert() 方法,但其實還有更好的方法,即使用 emplace() 或者 emplace_hint() 方法,它們完成“向容器中添加新鍵值對”的效率,要比 insert() 方法高。

              unordered_map emplace()方法

              emplace() 方法的用法很簡單,其語法格式如下:

              template

              pair emplace ( Args&&... args );

              其中,參數 args 表示可直接向該方法傳遞創建新鍵值對所需要的 2 個元素的值,其中第一個元素將作為鍵值對的鍵,另一個作為鍵值對的值。也就是說,該方法無需我們手動創建鍵值對,其內部會自行完成此工作。

              另外需要注意的是,該方法的返回值為 pair 類型值,其包含一個迭代器和一個 bool 類型值:

              • 當 emplace() 成功添加新鍵值對時,返回的迭代器指向新添加的鍵值對,bool 值為 True;
              • 當 emplace() 添加新鍵值對失敗時,說明容器中本就包含一個鍵相等的鍵值對,此時返回的迭代器指向的就是容器中鍵相同的這個鍵值對,bool 值為 False。

              include 
              include 
              include 
              using namespace std;
              int main()
              {
              //創建 umap 容器
              unordered_map umap;
              //定義一個接受 emplace() 方法的 pair 類型變量
              pair::iterator, bool> ret;
              //調用 emplace() 方法
              ret = umap.emplace(&34;STL教程&34;, &34;http://c.biancheng.net/stl/&34;);
              //輸出 ret 中包含的 2 個元素的值
              cout << &34;bool =&34; << ret.second << endl;
              cout << &34;iter ->&34; << ret.first->first << &34; &34; << ret.first->second << endl;
              return 0;
              }

              程序執行結果為:

              bool =1

              iter ->STL教程 http://c.biancheng.net/stl/

              通過執行結果中 bool 變量的值為 1 可以得知,emplace() 方法成功將新鍵值對添加到了 umap 容器中。

              unordered_map emplace_hint()方法

              emplace_hint() 方法的語法格式如下:

              template

              iterator emplace_hint ( const_iterator position, Args&&... args );

              和 emplace() 方法相同,emplace_hint() 方法內部會自行構造新鍵值對,因此我們只需向其傳遞構建該鍵值對所需的 2 個元素(第一個作為鍵,另一個作為值)即可。不同之處在于:

              • emplace_hint() 方法的返回值僅是一個迭代器,而不再是 pair 類型變量。當該方法將新鍵值對成功添加到容器中時,返回的迭代器指向新添加的鍵值對;反之,如果添加失敗,該迭代器指向的是容器中和要添加鍵值對鍵相同的那個鍵值對。
              • emplace_hint() 方法還需要傳遞一個迭代器作為第一個參數,該迭代器表明將新鍵值對添加到容器中的位置。需要注意的是,新鍵值對添加到容器中的位置,并不是此迭代器說了算,最終仍取決于該鍵值對的鍵的值。

              可以這樣理解,emplace_hint() 方法中傳入的迭代器,僅是給 unordered_map 容器提供一個建議,并不一定會被容器采納。

              舉個例子:

              include 
                include 
                include 
                using namespace std;
              int main(){    
                //創建 umap 容器    
                unordered_map umap;  
                //定義一個接受 emplace_hint() 方法的迭代器    
                unordered_map::iterator iter;   
                //調用 empalce_hint() 方法  
                iter = umap.emplace_hint(umap.begin(),&34;STL教程&34;, &34;http://c.biancheng.net/stl/&34;);    
                //輸出 emplace_hint() 返回迭代器 iter 指向的鍵值對的內容   
                cout << &34;iter ->&34; << iter->first << &34; &34; << iter->second << endl;  
                return 0;
              }

              程序執行結果為:

              iter ->STL教程 http://c.biancheng.net/stl/

              相關話題

              • 蘋果5配件價格表(5)
              • 2至3歲兒童單車的價格(2000元左右)
              • 成都恒大曹家巷廣場開盤價格暴跌(真降了)
              • 京陽光電動車價格圖片(這3款符合標準的低速四輪車)
              • 速騰瓦膽電飯煲價格(德州金車匯眾)
              • 河源房價2016最新價格(河源5月最新房價表)
              • weetbix麥片官方價格(減量不減價)
              • 新疆主焦煤價格(焦煤行業深度報告)
              • 2017年5月29日雞蛋價格(2017年9月29日禽蛋價格行情)
              • 北京駕校價格2017(北京駕考指南來啦)
              • 心可舒顆粒價格(3個中成藥養心穩心舒心)
              • 米石真空節能鍋價格(大美梁野山)
              • 黃山毛峰小罐茶價格(小罐茶年銷售額達20億)
              • 今日廣東黃顙魚價格(最高飆升2元)
              • 山東三元仔豬價格行情(10月29日豬價)
              • 紅星xo白蘭地價格(餐廳酒吧)
              • 科定木飾面板價格(木飾面貼墻)
              • 歐萊雅火山巖價格(這些)
              • 最新太陽能汽車價格(太陽能屋頂產業專題報告)
              • 水電改造價格人工費(水電改造新報價行情)

              熱門推薦

              • 古鐘二鍋頭46度多少錢(全國喝啥酒)
              • 順豐寄50斤冰箱多少錢(評測五大快遞平臺)
              • 做飯保姆一個月多少錢(52歲阿姨哭訴)
              • 鹿茸補腎丸多少錢一盒(參茸鞭丸腎陰虛者能吃嗎)
              • 北京換烤瓷牙多少錢(明星為整牙有多拼)
              • 樂高培訓加盟費多少錢(樂高教育取消授權波及上百門店)
              • 西鳳酒15年多少錢一瓶(價不高待客又不失面子的純糧酒)
              • 聚酰亞胺多少錢一公斤(酶中戰斗機)
              • 公司入職體檢一般多少錢(通過聘多多找到工作)
              • 插座維修上門多少錢(換個插座還用找電工)
              • 二元店一年掙多少錢(揭秘)
              • ctfau750鉆戒多少錢(黑客游戲和解謎游戲的關聯之處)
              • 23年工齡退休拿多少錢(繳費23年)
              • 平衡霜多少錢一瓶(日本POLA旗下這個小眾牌子THREE)
              • 歐米茄手表電池多少錢一塊(福布斯公布運動員收入榜單)
              • 正規醫院種植牙多少錢一顆(成本百元卻賣上萬)
              • 微信能賣多少錢(微信賬號被公開買賣)
              • 奔富707多少錢一瓶(宴請時的)
              • 超聲波焊接機多少錢一臺(關于超聲波焊接)
              • 一鳴加盟費要多少錢(一鳴真鮮奶吧多少錢)

              高悅明

              關注
              免責聲明:本文章由會員“高悅明”發布,如果文章侵權,請聯系我們處理,本站僅提供信息存儲空間服務 如因作品內容、版權和其他問題請于本站聯系

              關注排行榜

              1. 1新百倫多少錢(都有一個)
              2. 2活牛多少錢一斤(牛價丨2月11日)
              3. 3鋁單板多少錢一平方(鋁單板廠家報價大揭秘)
              4. 4一箱牛奶多少錢(實體店一箱牛奶賣50元)
              5. 5普洱茶一般多少錢(有的普洱茶只要幾十有的上萬)
              6. 6換手機外屏多少錢(盤點各個旗艦手機換屏價格)
              7. 7一輛電動車多少錢(最低不到8000元)
              8. 8巴寶莉圍巾多少錢(花2580元網購的博柏利圍巾竟系假貨)
              9. 9養老保險每年多少錢(2021年養老保險繳費15年)
              10. 10每升油多少錢(?定了)

              編輯精選

              Copyright ?2009-2022 KeJiTian.Com, All Rights Reserved

              版權所有 未經許可不得轉載

              增值電信業務經營許可證備案號:遼ICP備14006349號

              網站介紹 商務合作 免責聲明 - html - txt - xml

              感谢您访问我们的网站,您可能还对以下资源感兴趣:

              经典香港**毛片免费看_91精品一区二区综合在线_欧美人与性动交a欧美精品_国产小视频在线看