C++中map的基本操作


map

在STL的頭文件中map中定義了模版類map和multimap,用有序二叉樹表存儲類型為pair<const Key, T>的元素對序列。序列中的元素以const Key部分作為標識,map中所有元素的Key值必須是唯一的,multimap則允許有重復的Key值。可以將map看作是由Key標識元素的元素集合,這類容器也被稱為“關聯容器”,可以通過一個Key值來快速決定一個元素,因此非常適合於需要按照Key值查找元素的容器。map容器按照key的大小自動進行排序,默認升序。

定義map對象的代碼示例:

map<string, int> m;

 

在介紹關聯容器操作之前,先了解一下pair的標准庫類型。pair類型是在有文件utility中定義的,pair是將2個數據組合成一組數據,當需要這樣的需求時就可以使用pair,如STL中的map就是將key和value放在一起來保存。另一個應用是,當一個函數需要返回2個數據的時候,可以選擇pair。 pair的實現是一個結構體,主要的兩個成員變量是first ,second 因為是使用struct不是class,所以可以直接使用pair的成員變量。


pair類型包含了兩個數據值,通常有以下的一些定義和初始化的一些方法:

pair<T1, T2> p;         //定義了一個空的pair對象p,T1和T2的成員都進行了值初始化
pair<T1, T2> p(v1, v2); // p是一個成員類型為T1和T2的pair; first和second成員分別用v1和v2進行初始化。
make_pair(v1, v2);      //以v1和v2值創建的一個新的pair對象

 

map的基本操作 

 

向map中插入元素 

m[key] = value;

m.insert(make_pair(key, value));                               

[key]操作是map很有特色的操作,如果在map中存在鍵值為key的元素對, 則返回該元素對的值域部分,否則將會創建一個鍵值為key的元素對,值域為默認值。所以可以用該操作向map中插入元素對或修改已經存在的元素對的值域部分。

也可以直接調用insert方法插入元素對,insert操作會返回一個pair,當map中沒有與key相匹配的鍵值時,其first是指向插入元素對的迭代器,其second為true;若map中已經存在與key相等的鍵值時,其first是指向該元素對的迭代器,second為false。

即,insert可能插入失敗,用一下代碼可以檢查是否插入成功:

pair<map<key,value >::iterator, bool> Insert_Pair;
Insert_Pair = m.insert(make_pair(key, value));
if(!Insert_Pair.second)
cout << ""Error insert new element" << endl;

查找元素 

m[key];

當與該鍵值相匹配的元素對存在時,返回對應的值value。要注意的是,當與該鍵值相匹配的元素對不存在時,會創建鍵值為key(當另一個元素是整型時,m[key]=0)的元素對。

map<key, value>::iterator it = m.find(key);

如果map中存在與key相匹配的鍵值時,find操作將返回指向該元素對的迭代器,否則,返回的迭代器等於map的end()(參見vector中提到的begin()和end()操作)。

刪除元素 

m.erase(key);

刪除與指定key鍵值相匹配的元素對,並返回被刪除的元素的個數。

m.erase(it);

有的說m.erase(it)返回指向像一個元素的迭代器,但我的實際操作發現返回的是void,一些博客也提到了這一點。建議是當作返回void使用...

要注意進行安全的刪除操作!

錯誤示范:

for(map<key,value >::iterator iter=m.begin();iter!=m.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
m.erase(iter);
}

這是一種錯誤的寫法,會導致程序行為不可知.究其原因是map 是關聯容器,對於關聯容器來說,如果某一個元素已經被刪除,那么其對應的迭代器就失效了,不應該再被使用;否則會導致程序無定義的行為。(但是有的博客用這種方法也能得出正確的結果,不過這里提到的無定義行為也有道理,先暫且將這種方法視為錯誤的方法吧)

正確示范:

for(map<key,value >::iterator iter=m.begin();iter!=m.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
m.erase(iter++);
}

這種刪除方式也是STL源碼一書中推薦的方式,分析 m.erase(it++)語句,map中在刪除iter的時候,先將iter做緩存,然后執行iter++使之指向下一個結點,再進入erase函數體中執行刪除操作,刪除時使用的iter就是緩存下來的iter(也就是當前iter(做了加操作之后的iter)所指向結點的上一個結點)。

(m.erase(it++) )和(m.erase(it); iter++; )這個執行序列是不相同的。前者在erase執行前進行了加操作,在it被刪除(失效)前進行了加操作,是安全的;后者是在erase執行后才進行加操作,而此時iter已經被刪除(當前的迭代器已經失效了),對一個已經失效的迭代器進行加操作,行為是不可預期的,這種寫法勢必會導致 map操作的失敗並引起進程的異常。

其他操作 

m.size();

返回元素個數

m.empty();

判斷是否為空

m.clear(); 

清空所有元素

 

參考鏈接:

https://blog.csdn.net/forever__1234/article/details/89647975

https://blog.csdn.net/u010029439/article/details/89681773

https://xuanxuanblingbling.github.io/life/study/2019/03/20/STL/

https://www.cnblogs.com/zhoulipeng/p/3432009.html

https://www.cnblogs.com/kex1n/archive/2011/12/06/2278505.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM