C++ primer摘要(7)---順序容器

順序容器

  • 元素在順序容器中的順序與加入容器時的位置相對應
  • 關(guān)聯(lián)容器中元素的位置由元素相關(guān)聯(lián)的關(guān)鍵字值決定

順序容器概述

  • 所有順序列表都提供了快速順序訪問元素的能力,但是,這些容器在以下方面都有不同程度的性能折中
- [x] 向容器添加或從容器中刪除元素的代價
- [x] 非順序訪問容器中元素的代價
vector          //可變大小數(shù)組坞古,支持快速隨機訪問,在尾部之外的位置插入或刪除元素可能很慢
deque           //雙端隊列,支持快速隨機訪問揩局,在頭尾位置插入/刪除速度很快
list            //雙向鏈表,只支持雙向順序訪問掀虎,在list中任何位置進行插入/刪除都很快
forward_list    //單向鏈表凌盯,只支持單向順序訪問,在鏈表任何位置進行插入/刪除都很快
array           //固定大小數(shù)組烹玉,支持快速隨機訪問驰怎,不能添加或刪除元素
string          //與vector相似的容器,但專門用于保存字符二打,隨機訪問快县忌,在尾部插入/刪除速度快
  • 除了對固定大小的array外,其他容器都提供高效继效、靈活的內(nèi)存管理
  • 容器保存元素的策略對容器操作的效率有著固有的症杏,甚至是重大的影響,在某些情況下瑞信,存儲策略還會影響特定容器是否支持特定操作
  • stringvector將元素保存在連續(xù)的內(nèi)存空間中厉颤,由于元素是連續(xù)存儲的,由元素的下標來計算其地址是十分快速的喧伞,但是走芋,在這兩種容器的中間位置添加或刪除元素就會非常耗時
  • 與內(nèi)置數(shù)組相比,array是一種更安全潘鲫,更容器使用的數(shù)組類型
  • 通常翁逞,使用vector是最好的選擇
  • 選擇容器的基本原則
- [x] 除非有很好的理由選擇其他容器,否自使用vector
- [x] 如果程序要求隨機訪問溉仑,使用vector或deque
- [x] 如果程序要求在容器的中間插入或刪除元素挖函,應該使用list或forward_list
- [x] 如果程序需要在頭尾插入或刪除元素,但不會在中間位置進行插入或刪除操作浊竟,使用deque
  • 如果不確定使用哪種容器怨喘,那么可以在程序中只使用vector和list公共的操作:使用迭代器,不使用下標操作振定,避免隨機訪問必怜,這樣在必要時選擇使用vector或list都很方便

容器庫概覽

  • 每個容器都定義在一個頭文件中,文件名與類型名相同
  • 順序容器幾乎可以保存任意類型的元素后频,包括元素類型可以是另一個容器
vector<vector<string>> lines;   //vector的vector
迭代器
  • forward_list迭代器不支持遞減運算符(--)
  • 迭代器范圍的概念是標準庫的基礎
  • 一個迭代器范圍由一對迭代器表示梳庆,兩個迭代器分別指向同一個容器中首元素或者是尾元素之后的位置暖途,它們標記了容器中元素的一個范圍
begin和end成員
  • begin和end有多個版本:帶r的版本返回反向迭代器,以c開頭的版本返回cosnt迭代器
list<string> a;
auto it1 = a.begin();   //list<string>::iterator
auto it2 = a.rbegin();  //list<string>::reverse_iterator
auto it3 = a.cbegin();  //list<string>::const_iterator
auto it4 = a.crbegin(); //list<string>::const_reverse_iterator
  • 當不需要寫訪問時,應該使用cbegin和cend
容器定義和初始化
  • 每個容器類型都定義了一個默認的構(gòu)造函數(shù)膏执,除array之外驻售,其他容器的默認構(gòu)造函數(shù)都會創(chuàng)建一個指定類型的空容器,且都可以接受指定容器大小和元素初始值的參數(shù)
  • 當將一個容器初始化為另一個容器的拷貝時更米,兩個容器的容器類型和元素類型必須相同
  • 只有順序容器的構(gòu)造函數(shù)才接受大小參數(shù)欺栗,關(guān)聯(lián)容器并不支持
  • 當定義一個array時,必須指定元素類型和容器大小
array<int,10> temp;
賦值和swap
  • 賦值相關(guān)運算會導致指向左邊容器內(nèi)部的迭代器征峦、引用和指針失效迟几,而swap操作將容器內(nèi)容交換不會導致指向容器的迭代器、引用和指針失效(容器類型為array和string的情況除外)
容器大小操作
  • 每個容器類型都有三個與大小相關(guān)的操作
- [x] size 返回容器中元素的數(shù)目
- [x] empty 當size為0時返回true眶痰,反之返回false
- [x] max_size 返回一個大于或等于該類型容器所能容納的最大元素數(shù)的值
- [x] forward_list支持max_list和empty瘤旨,但不支持size
關(guān)系運算符
  • 除無序關(guān)聯(lián)容器外的所有容器都支持關(guān)系運算符,關(guān)系運算符左右兩邊的運算對象必須是相同類型的容器竖伯,且必須保存相同類型的元素
vector<int> v1 = {1,3,5,7,9,12};
vector<int> v2 = {1,3,9};
vector<int> v3 = {1,3,5,7};
vector<int> v4 = {1,3,5,7,9,12};

v1 < v2     //true v1和v2在元素[2]處不同存哲,v1[2]小于v2[2]
v1 < v3     //false 所有元素相等,但v3中元素數(shù)目少
v1 == v4    //true 每個元素相等七婴,且v1和v4大小相同
v1 == v2    //false v2元素數(shù)目比v1少
  • 只有當其元素運算符也定義了相應的比較運算符時祟偷,我們才可以使用關(guān)系運算符來比較兩個容器

順序容器操作

  • 順序容器和關(guān)聯(lián)容器的不同之處在于兩者組織元素的方式,這些不同之處直接關(guān)系到了元素如何存儲打厘、訪問修肠、添加以及刪除
順序容器添加元素
  • 除了array外,所有標準庫容器都提供靈活的內(nèi)存管理户盯,在運行時可以動態(tài)添加或刪除元素來改變?nèi)萜鞔笮?/li>
  • 向一個vector嵌施、string或deque插入元素會使所有指向容器的迭代器、引用和指針失效
  • 將元素插入到vector莽鸭、deque和string中的任何位置都是合法的吗伤,然而,這樣做可能會很耗時
  • C++11引入了三個新成員
- [x] emplace_front對應push_fromt
- [x] emplace對應insert
- [x] emplace_back對應push_back
  • emplace函數(shù)在容器中直接構(gòu)造元素硫眨,傳遞給emplace函數(shù)的參數(shù)必須與元素類型的構(gòu)造函數(shù)相匹配足淆,并且emplace操作比相對應的push操作更快
訪問元素
  • 對一個空容器調(diào)用front和back,就像使用一個越界的下標一樣礁阁,是一種嚴重的程序設計錯誤
  • 訪問成員函數(shù)返回的是引用
if(!c.empty()){
    c.front() = 42;         //將42賦予c中的第一個元素
    auto & v = c.back();    //獲得指向最后一個元素的引用
    v = 1024;               //改變c中的元素
    auto v2 = c.back();     //v2不是一個引用巧号,它是c.back()的一個拷貝
    v2 = 0;                 //未改變c中的元素
}
  • 下標操作和安全的隨機訪問
- [x] `string`、`vector`姥闭、`deque`丹鸿、 `array`這幾個容器都提供快速隨機訪問
刪除元素
  • 刪除元素的成員函數(shù)并不檢查其參數(shù),在刪除元素之前棚品,程序猿必須確保它是存在的
  • vectorstring不支持pop_front
  • 成員函數(shù)erase從容器中指定位置刪除元素卜高,返回指向刪除的最后一個元素之后的位置的迭代器
  • ww36可以用resize來增大或縮小容器弥姻,但array不支持resize
  • 向容器中添加或刪除元素的操作可能會使指向容器元素的指針、引用掺涛、迭代器失效,失效的指針疼进、引用薪缆、迭代器將不再表示任何元素,使用它們是嚴重的程序設計錯誤
  • 由于向迭代器添加元素和從迭代器刪除元素的代碼可能會使迭代器失效伞广,因此必須保證每次改變?nèi)萜鞯牟僮髦蠖颊_地重新定位迭代器拣帽,對于vector、string嚼锄、deque尤為重要
  • 不要保存end返回地迭代器
- [x] 添加或刪除元素地循環(huán)程序必須反復調(diào)用end减拭,而不能在循環(huán)之前保存end返回的迭代器

vector對象是如何增長的

  • 當不得不獲取新的內(nèi)存空間時,vector和string地實現(xiàn)通常會分配比新地空間需求更大的內(nèi)存空間区丑,容器預留這些空間作為備用
  • capacity函數(shù)表示在不分配新的內(nèi)存的情況下vector或string最多可以保存多少個元素
  • size函數(shù)表示vector或string當前已經(jīng)保存的元素的數(shù)量
  • 可以調(diào)用shrink_to_fit函數(shù)來要求vector將超出當前大小的多余內(nèi)存退回給系統(tǒng)
  • 每個vector實現(xiàn)都可以選擇自己的內(nèi)存分配策略拧粪,但是必須遵守的一條原則是:只有當迫不得已時才可以分配新的內(nèi)存空間
  • 通過在一個初始為空的vector上調(diào)用n次push_back來創(chuàng)建一個n個元素的vector,所花費的時間不能超過n的常數(shù)倍

額外的string操作

  • 通常當我們從一個const char *創(chuàng)建string時沧侥,指針指向的數(shù)組必須以空字符結(jié)尾
substr操作
string s("hello world");
string s2 = s.substr(0,5);  //s2 = hello
數(shù)值轉(zhuǎn)換
int i = 42;
string s = to_string(i);    //將整數(shù)i轉(zhuǎn)換為字符表示形式
double d = stod(s);         //將字符串s轉(zhuǎn)換為浮點數(shù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末可霎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子宴杀,更是在濱河造成了極大的恐慌癣朗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旺罢,死亡現(xiàn)場離奇詭異旷余,居然都是意外死亡,警方通過查閱死者的電腦和手機扁达,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門正卧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罩驻,你說我怎么就攤上這事穗酥。” “怎么了惠遏?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵砾跃,是天一觀的道長。 經(jīng)常有香客問我节吮,道長抽高,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任透绩,我火速辦了婚禮翘骂,結(jié)果婚禮上壁熄,老公的妹妹穿的比我還像新娘。我一直安慰自己碳竟,他們只是感情好草丧,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著莹桅,像睡著了一般昌执。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诈泼,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天懂拾,我揣著相機與錄音,去河邊找鬼铐达。 笑死岖赋,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瓮孙。 我是一名探鬼主播唐断,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼衷畦!你這毒婦竟也來了栗涂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤祈争,失蹤者是張志新(化名)和其女友劉穎斤程,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菩混,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡忿墅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沮峡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疚脐。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖邢疙,靈堂內(nèi)的尸體忽然破棺而出棍弄,到底是詐尸還是另有隱情,我是刑警寧澤疟游,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布呼畸,位于F島的核電站,受9級特大地震影響颁虐,放射性物質(zhì)發(fā)生泄漏蛮原。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一另绩、第九天 我趴在偏房一處隱蔽的房頂上張望儒陨。 院中可真熱鬧花嘶,春花似錦、人聲如沸蹦漠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笛园。三九已至拆撼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喘沿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工竭贩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蚜印,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓留量,卻偏偏與公主長得像窄赋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子楼熄,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355