日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ primer 第9章 顺序容器

發(fā)布時(shí)間:2023/12/13 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ primer 第9章 顺序容器 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 順序容器類型
    • 確定使用哪種順序容器
  • 容器庫概覽
    • 容器操作
    • 迭代器
      • 迭代器支持的所有操作
      • 迭代器支持的所有運(yùn)算
      • 迭代器范圍
        • 對(duì)構(gòu)成范圍的迭代器的要求
        • 標(biāo)準(zhǔn)庫迭代器范圍左閉右開的三種性質(zhì)
    • 容器定義和初始化
      • 將一個(gè)新容器創(chuàng)建為另一個(gè)容器的拷貝
        • 將array拷貝到vector中的代碼
      • 與順序容器大小相關(guān)的構(gòu)造函數(shù)
      • 標(biāo)準(zhǔn)庫array具有固定大小
    • 賦值和swap
      • 測試swap的代碼
    • 關(guān)系運(yùn)算符
  • 順序容器的特有操作
    • 向順序容器添加元素
      • 容器元素是拷貝
      • 在容器中特定位置添加元素:insert
      • emplace操作
    • 訪問元素
      • 訪問成員函數(shù)返回的是引用
    • 刪除元素
    • 特殊的forward_list操作
    • 改變?nèi)萜鞔笮?/li>
    • 容器操作可能使迭代器失效
  • vector對(duì)象是如何增長的
    • capacity和size
  • 額外的string操作
    • 構(gòu)造string的其他方法
    • substr操作
    • 從一個(gè)vector \

順序容器類型


string和vector將元素保存在連續(xù)的內(nèi)存空間中,因此支持快速隨機(jī)訪問,但是在這兩種容器的中間位置添加或刪除元素會(huì)非常耗時(shí),因?yàn)樾枰苿?dòng)插入/ 刪除位置之后的所有元素,來保持連續(xù)存儲(chǔ)。而且添加一個(gè)元素有時(shí)可能還需要分配額外的存儲(chǔ)空間,這種情況下,每個(gè)元素都必須移動(dòng)到新的存儲(chǔ)空間中。
list和forward_list兩個(gè)容器添加和刪除操作快速,但不支持元素的隨機(jī)訪問,為了訪問一個(gè)元素只能遍歷整個(gè)容器,其存儲(chǔ)的內(nèi)存空間不連續(xù)。
deque支持快速隨機(jī)訪問,中間位置添加或刪除元素非常耗時(shí),但是在deque的兩端添加或刪除元素很快。

確定使用哪種順序容器

通常,使用vector是最好的選擇,除非你有很好的理由選擇其他容器。

容器庫概覽

一般來說,每個(gè)容器都定義在一個(gè)頭文件中,文件名與類型名相同,即deque定義在頭文件deque中,list定義在頭文件list中,以此類推。容器均定義為模板類,例如對(duì)vector,我們必須提供額外信息來生成特定的容器類型。對(duì)大多數(shù),但不是所有容器,我們還需要額外提供元素類型信息:

list<Sales_data> 保存Sales_data對(duì)象的list
deque<double> 保存double的deque

順序容器幾乎可以保存任意類型的元素。特別是,我們可以定義一個(gè)容器,其元素的類型是另一個(gè)容器。這種容器的定義與任何其他容器類型完全一樣:

vector<vector<string>> lines; 此處lines是一個(gè)vector,其元素類型是string的vector

容器操作


迭代器

迭代器支持的所有操作

forward_list迭代器不支持遞減運(yùn)算符

迭代器支持的所有運(yùn)算

這些運(yùn)算只適用于string、vector、deque和array的迭代器,我們不能將它們用于其他任何容器類型的迭代器。

例如,list的迭代器不支持<運(yùn)算,只支持遞增、遞減、==以及!=運(yùn)算,原因在于list是將元素以鏈表方式存儲(chǔ),在內(nèi)存中不連續(xù),兩個(gè)指針的大小關(guān)系與它們指向的元素的前后關(guān)系并不一定是吻合的,實(shí)現(xiàn)<運(yùn)算將會(huì)非常困難和低效。

迭代器范圍

一個(gè)迭代器范圍由一對(duì)迭代器表示,兩個(gè)迭代器分別指向同一個(gè)容器中的元素或者是尾元素之后的位置。這兩個(gè)迭代器通常被稱為begin和end

對(duì)構(gòu)成范圍的迭代器的要求

如果滿足如下條件,兩個(gè)迭代器begin和end構(gòu)成一個(gè)迭代器范圍:
它們指向同一個(gè)容器中的元素,或者是容器最后一個(gè)元素之后的位置,且我們可以通過反復(fù)遞增begin來到達(dá)end。換句話說,end不在begin之前。

標(biāo)準(zhǔn)庫迭代器范圍左閉右開的三種性質(zhì)

假定begin和end構(gòu)成一個(gè)合法的迭代器范圍,則

  • 如果begin與end相等,則范圍為空
  • 如果begin與end不相等,則范圍至少包含一個(gè)元素,且begin指向該范圍中的第一個(gè)元素
  • 我們可以對(duì)begin遞增若干次,使得begin==end

容器定義和初始化

每個(gè)容器類型都定義了一個(gè)默認(rèn)構(gòu)造函數(shù)。除array之外,其他容器的默認(rèn)構(gòu)造函數(shù)都會(huì)創(chuàng)建一個(gè)指定類型的空容器,且都可以接受指定容器大小和元素初始值的參數(shù)。

將一個(gè)新容器創(chuàng)建為另一個(gè)容器的拷貝

為了創(chuàng)建一個(gè)容器為另一個(gè)容器的拷貝,兩個(gè)容器的類型及其元素類型必須匹配。不過,當(dāng)傳遞迭代器參數(shù)來拷貝一個(gè)范圍時(shí),就不要求容器類型是相同的了,而且新容器和原容器中的元素類型也可以不同,只要能將要拷貝的元素轉(zhuǎn)換為要初始化的容器的元素類型即可。

將array拷貝到vector中的代碼

int ia[] = { 0,1,1,2,3,5,8,13,21,55,89 }; vector<int>vect; vect.assign(ia,ia+11);

與順序容器大小相關(guān)的構(gòu)造函數(shù)

如果元素類型是內(nèi)置類型或者是具有默認(rèn)構(gòu)造函數(shù)的類類型,可以只為構(gòu)造函數(shù)提供一個(gè)容器大小參數(shù)。如果元素類型沒有默認(rèn)構(gòu)造函數(shù),除了大小參數(shù)外,還必須指定一個(gè)顯式的元素初始值。
只有順序容器的構(gòu)造函數(shù)才接受大小參數(shù),關(guān)聯(lián)容器并不支持。

標(biāo)準(zhǔn)庫array具有固定大小

與內(nèi)置數(shù)組一樣,標(biāo)準(zhǔn)庫array的大小也是類型的一部分。當(dāng)定義一個(gè)array時(shí),除了指定元素類型,還要指定容器大小,例如array<int,42>
與其他容器不同,一個(gè)默認(rèn)構(gòu)造的array是非空的:它包含了與其大小一樣多的元素。這些元素都被默認(rèn)初始化。如果我們對(duì)array進(jìn)行列表初始化,則初始值的數(shù)目必須等于或小于array的大小。如果初始值數(shù)目小于array的大小,則它們被用來初始化array中靠前的元素,所有剩余元素都會(huì)進(jìn)行值初始化。在這兩種情況下,如果元素類型是一個(gè)類類型,那么該類必須有一個(gè)默認(rèn)構(gòu)造函數(shù),以使值初始化能夠進(jìn)行。

我們不能對(duì)內(nèi)置數(shù)組類型進(jìn)行拷貝或?qū)ο筚x值操作,但array并無此限制:

賦值和swap

與內(nèi)置數(shù)組不同,標(biāo)準(zhǔn)庫array類型允許賦值,賦值后左右兩邊的運(yùn)算對(duì)象需具有相同的類型:

array<int, 10>a1 = {0,1,2,3,4,5,6,7,8,9}; array<int, 10>a2 = { 0 }; a1 = a2;//此時(shí)a1中的元素為10個(gè)0


除array外,swap不對(duì)任何元素進(jìn)行拷貝、刪除或插入操作,因此可以保證在常數(shù)時(shí)間內(nèi)完成。
除string外, 指向容器的迭代器、引用和指針在swap操作之后都不會(huì)失效,它們?nèi)灾赶騭wap操作之前所指向的那些元素,但是在swap之后,這些元素已經(jīng)屬于不同的容器了,詳情可見對(duì)vector進(jìn)行測試的代碼。與其他容器不同,swap兩個(gè)array會(huì)真正交換它們的元素,因此,對(duì)于array,在swap操作之后,指針、引用和迭代器所綁定的元素保持不變,但元素值已經(jīng)與另一個(gè)array中對(duì)應(yīng)元素的值進(jìn)行了交換,詳情可見對(duì)array進(jìn)行測試的代碼。

測試swap的代碼

對(duì)array進(jìn)行測試的代碼

int main() {array<int, 10>a1 = {1};array<int, 10>a2 = {0};auto beg1 = a1.begin();auto beg2 = a2.begin();cout << "swap之前:" << endl;cout << "a1元素:";for (auto a : a1) {cout << a << " ";}cout << endl;cout << "a2元素:";for (auto a : a2) {cout << a << " ";}cout << endl;cout << "a1.begin:"<< *beg1 << endl;cout << "a2.begin:" << *beg2 << endl;swap(a1,a2);cout << "swap之后:"<<endl;cout << "a1元素:";for (auto a : a1) {cout << a << " ";}cout << endl;cout << "a2元素:";for (auto a:a2) {cout << a << " ";}cout << endl;cout << "a1.begin:" << *beg1 << endl;cout << "a2.begin:" << *beg2 << endl;system("pause");return 0; }

測試結(jié)果:

swap之前: a1元素:1 0 0 0 0 0 0 0 0 0 a2元素:0 0 0 0 0 0 0 0 0 0 a1.begin:1 a2.begin:0 swap之后: a1元素:0 0 0 0 0 0 0 0 0 0 a2元素:1 0 0 0 0 0 0 0 0 0 a1.begin:0 a2.begin:1

對(duì)vector進(jìn)行測試的代碼:

int main() {vector<int>a1 = {1};vector<int>a2 = {0};auto beg1 = a1.begin();auto beg2 = a2.begin();cout << "swap之前:" << endl;cout << "a1元素:";for (auto a : a1) {cout << a << " ";}cout << endl;cout << "a2元素:";for (auto a : a2) {cout << a << " ";}cout << endl;cout << "a1.begin:"<< *beg1 << endl;cout << "a2.begin:" << *beg2 << endl;swap(a1,a2);cout << "swap之后:"<<endl;cout << "a1元素:";for (auto a : a1) {cout << a << " ";}cout << endl;cout << "a2元素:";for (auto a:a2) {cout << a << " ";}cout << endl;cout << "a1.begin:" << *beg1 << endl;cout << "a2.begin:" << *beg2 << endl;system("pause");return 0; }

測試結(jié)果:

swap之前: a1元素:1 a2元素:0 a1.begin:1 a2.begin:0 swap之后: a1元素:0 a2元素:1 a1.begin:1 a2.begin:0

關(guān)系運(yùn)算符

每個(gè)容器都支持相等運(yùn)算符(==和 !=),除了無序關(guān)聯(lián)容器外的所有容器都支持關(guān)系運(yùn)算符(>,>=,<,<=),關(guān)系運(yùn)算符左右兩邊的運(yùn)算對(duì)象必須是相同類型的容器,且必須保存相同類型的元素。
比較兩個(gè)容器實(shí)際上是進(jìn)行元素的逐對(duì)比較:

  • 如果兩個(gè)容器具有相同大小且所有元素都兩兩對(duì)應(yīng)相等,則這兩個(gè)容器相等;否則兩個(gè)容器不等
  • 如果兩個(gè)容器大小不同,但較小容器中每個(gè)元素都等于較大容器中的對(duì)應(yīng)元素,則較小容器小于較大容器
  • 如果兩個(gè)容器都不是另一個(gè)容器的前綴子序列,則它們的比較結(jié)果取決于第一個(gè)不相等的元素的比較結(jié)果

順序容器的特有操作

向順序容器添加元素

除array外,所有標(biāo)準(zhǔn)庫容器都提供靈活的內(nèi)存管理,在運(yùn)行時(shí)可以動(dòng)態(tài)添加或刪除元素來改變?nèi)萜鞔笮 ?br />

容器元素是拷貝

當(dāng)我們用一個(gè)對(duì)象來初始化容器時(shí),或?qū)⒁粋€(gè)對(duì)象插入到容器中時(shí),實(shí)際上放入到容器中的是對(duì)象值的一個(gè)拷貝,而不是對(duì)象本身。容器中的元素與提供值的對(duì)象之間沒有任何關(guān)聯(lián),隨后對(duì)容器中元素的任何改變都不會(huì)影響到原始對(duì)象,反之亦然。

在容器中特定位置添加元素:insert

在新標(biāo)準(zhǔn)下,接受元素個(gè)數(shù)或范圍的insert版本返回指向第一個(gè)新加入元素的迭代器,如果范圍為空,不插入任何元素,insert操作會(huì)將第一個(gè)參數(shù)返回。
通過使用insert的返回值,可以在容器中一個(gè)特定位置反復(fù)插入元素。

s.iinsert(iter,"hello")"hello"添加到iter之前的位置 s.iinsert(iter,10,"hello") 將10個(gè)"hello"添加到iter之前的位置 s.insert(s.begin(),s2.begin(),s2.end()) 將指定范圍中的元素插入到給定迭代器位置之前 s.insert(s.begin(),{"the","haha","heihei"}) 將初始化列表中的元素插入到給定位置之前 s.insert(s.begin(),s.begin(),s.end()) 此句錯(cuò)誤,拷貝的范圍不能指向與目的位置相同的容器

emplace操作

訪問元素

訪問成員函數(shù)返回的是引用

在容器中訪問元素的成員函數(shù)(即,front、back、下標(biāo)和at)返回的都是引用。如果容器是一個(gè)const對(duì)象,則返回值是const的引用。如果容器不是const的,則返回值是普通引用,我們可以用來改變?cè)氐闹?#xff1a;

刪除元素

特殊的forward_list操作

改變?nèi)萜鞔笮?/h2>


示例代碼如下:

容器操作可能使迭代器失效

向容器中添加元素和從容器中刪除元素的操作可能會(huì)使指向容器元素的指針、引用或迭代器失效。一個(gè)失效的指針、引用或迭代器將不再表示任何元素。使用失效的指針、引用或迭代器是一種嚴(yán)重的程序設(shè)計(jì)錯(cuò)誤,很可能會(huì)引起與使用未初始化指針一樣的問題。

如果在一個(gè)循環(huán)中插入/刪除deque、string或vector中的元素,不要緩存end返回的迭代器,必須在每次操作后重新調(diào)用end(),而不能在循環(huán)開始前保存它返回的迭代器。

vector對(duì)象是如何增長的


reserve并不改變?nèi)萜髦性氐臄?shù)量,它僅影響vector預(yù)先分配多大的內(nèi)存空間。

capacity和size

容器的size是指它已經(jīng)保存的元素的數(shù)目;而capacity則是在不分配新的內(nèi)存空間的前提下它最多可以保存多少元素。

額外的string操作

除了順序容器共同的操作之外,string類型還提供了一些額外的操作,這些操作中的大部分要么是提供string類和c風(fēng)格字符數(shù)組之間的相互轉(zhuǎn)換,要么是增加了運(yùn)行我們用下標(biāo)代替迭代器的版本。

構(gòu)造string的其他方法


代碼示例:

substr操作


從一個(gè)vector <char> 初始化一個(gè)string

vector提供了一個(gè)data成員函數(shù),返回其內(nèi)存空間的首地址

vector<char>vi{ 'a','b' ,'c','d'}; string s(vi.begin(),vi.end()); string s2(vi.data(),vi.size());

改變string的其他方法


string的下標(biāo)版本的insert和erase版本

string類型支持順序容器的賦值運(yùn)算符以及assign、insert和erase操作,除此之外,它還定義了下標(biāo)版本的insert和erase版本:

string s="0123456789";s.insert(5, 3, 'A'); //此時(shí)s是01234AAA56789,即在s[5]之前插入3個(gè)‘A’string s1 = "0123456789";s1.erase(5, 3);//此時(shí)s1是0123489,即刪除s[5]之后的3個(gè)元素,包括s[5]

string的c風(fēng)格字符數(shù)組版本的insert和erase版本

const char *cp = "0123456789";string s;s.assign(cp,5); //s=="01234"s.insert(s.size(),cp+7);s=="01234789" string s = "some string";string s2 = "some other string ";s.insert(0,s2);//s=="some other string some string"// 在s[0]之前插入s2中s2[0]開始的s2.size()個(gè)字符s.insert(0,s2,0,s2.size());//s=="some other string some other string some string"

append和replace函數(shù)

string s="some "; s.append("things"); //s=="some things" s.replace(5,3,"hhhh");//s=="some hhhhngs"即從s[5]開始將3個(gè)元素,替換為“hhhh”

string搜索操作

string搜索操作,每個(gè)操作都返回一個(gè)string::size_type值,表示匹配位置的下標(biāo)。如果搜索失敗,則返回一個(gè)名為string::npos的static成員。

string find

find查找參數(shù)指定的字符串,若找到,則返回第一個(gè)匹配位置的下標(biāo),否則返回npos

string name("AnnaBelleAnnaBelle"); auto pos1=name.find("Anna");//pos1==0 auto pos2 = name.find("Anna",1);//pos2==9 此處是從name[1]處開始查找"Anna",返回第一個(gè)匹配位置的下標(biāo)

string find_first_of

string numbers("0123456789");string name("n1inin4n");auto pos1 = name.find_first_of(numbers,2);//pos1==6auto pos1 = name.find_first_of(numbers);//pos1==1

string compare函數(shù)

根據(jù)s是等于、大于還是小于參數(shù)指定的字符串,s.compare返回0、正數(shù)或負(fù)數(shù)。

數(shù)值轉(zhuǎn)換

int i = 42;string s = to_string(i);//將整數(shù)i轉(zhuǎn)換為字符“42”double num = stod(s);// 將字符“42”轉(zhuǎn)換為浮點(diǎn)數(shù)42 s = "00110011";int num = stoi(s,0,2);// 將s轉(zhuǎn)換為二進(jìn)制,num==51

容器適配器

除了順序容器外,標(biāo)準(zhǔn)庫還定義了三個(gè)順序容器適配器:stack、queue和priority_queue。
默認(rèn)情況下,stack和queue是基于deque實(shí)現(xiàn)的,priority_queue是在vector之上實(shí)現(xiàn)的。
適配器是標(biāo)準(zhǔn)庫中的一個(gè)通用概念,容器、迭代器和函數(shù)都有適配器。本質(zhì)上,一個(gè)適配器是一種機(jī)制,能使某種事物的行為看起來像另外一種事物一樣。一個(gè)容器適配器接受一種已有的容器類型,使其行為看起來像一種不同的類型。

所有容器適配器都支持的操作和類型

棧適配器

stack定義在stack頭文件中,先進(jìn)后出

隊(duì)列適配器

queue和priority_queue定義在queue頭文件中。
queue,先進(jìn)先出
priority_queue,允許我們?yōu)殛?duì)列中的元素建立優(yōu)先級(jí),新加入的元素會(huì)排在所有優(yōu)先級(jí)比它低的已有元素之前。默認(rèn)情況下,標(biāo)準(zhǔn)庫在元素類型上使用<運(yùn)算符來確定相對(duì)優(yōu)先級(jí)。

總結(jié)

以上是生活随笔為你收集整理的C++ primer 第9章 顺序容器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。