bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

【C++基礎(chǔ)】2.標(biāo)準(zhǔn)庫-創(chuàng)新互聯(lián)

8. IO庫
  • C++語言不直接處理輸入輸出,而是通過定義在標(biāo)準(zhǔn)庫中的類型來處理IO,這些類型支持從設(shè)備讀寫數(shù)據(jù),設(shè)備可以是文件、控制臺窗口等。還有一些類型允許內(nèi)存IO,即從string讀寫數(shù)據(jù)
  • 標(biāo)準(zhǔn)庫定義了3仲不同的IO處理操作,分別定義在3個獨立的頭文件中,iostream定義了用于讀寫流的基本類型,用于處理控制臺IO,fstream定義了讀寫命名文件的類型,sstream定義了讀寫內(nèi)存string對象的類型
  • fstreamstringstream都是繼承自類iostream,輸入類都繼承自istream,輸出類都繼承自ostream,因此在istream對象上執(zhí)行的操作,也可在ifstreamistringstream對象上執(zhí)行
  • 不能對IO對象進(jìn)行拷貝或賦值,因此也不能將形參或返回類型設(shè)置為流類型,進(jìn)行IO操作的函數(shù)通常以引用方式傳遞和返回流,讀寫一個IO對象會改變其狀態(tài),因此傳遞和返回的引用不能是const的
  • IO操作的一個問題是可能發(fā)生錯誤,有些錯誤是可恢復(fù)的,而有些錯誤是不可恢復(fù)的,因此代碼應(yīng)該在使用一個流之前檢查它是否處于良好狀態(tài),確定一個流對象狀態(tài)的最簡單方法是將它當(dāng)作一個條件來使用while(cin >>word),while循環(huán)檢查>>表達(dá)式返回的流的狀態(tài),如果輸入操作成功,流保持有效狀態(tài),則條件為真
  • 每個輸出流都管理一個緩沖區(qū),用來保存程序讀寫的數(shù)據(jù),如果執(zhí)行os<< "hello";,文本串可能會立即打印,也可能被保存在緩沖區(qū)中,導(dǎo)致緩沖刷新(數(shù)據(jù)真正寫到輸出設(shè)備中)的原因有:① 程序正常結(jié)束;② 緩沖區(qū)滿;③ 使用endl(添加換行)或flush(不添加)或ends(添加空字符)操作符顯式刷新緩沖區(qū);④ 使用unitbuf操作符使流在每次寫操作后都進(jìn)行一次flush操作;⑤ 一個輸出流可能被關(guān)聯(lián)到另一個流,當(dāng)讀寫被關(guān)聯(lián)的流時,關(guān)聯(lián)到的流緩沖區(qū)會被刷新,默認(rèn)情況下cincerr都關(guān)聯(lián)到cout
  • 如果程序崩潰,輸出緩沖區(qū)是不會被刷新的
  • 定義一個空文件流對象,可以調(diào)用成員函數(shù)open()將它與文件關(guān)聯(lián)起來,如果調(diào)用失敗則不能使用該對象,此時和cin一樣返回false,對一個已經(jīng)打開的文件流調(diào)用open()會失敗,并導(dǎo)致該對象不能被使用,為了將文件流關(guān)聯(lián)到另一個文件,必須先用成員函數(shù)close()關(guān)閉已經(jīng)關(guān)聯(lián)的文件,當(dāng)一個fstream對象離開其作用域時,與之關(guān)聯(lián)的文件會自動關(guān)閉(對象銷毀時,close()自動調(diào)用)
9. 順序容器

9.1 順序容器概述

成都創(chuàng)新互聯(lián)公司專注于景縣網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供景縣營銷型網(wǎng)站建設(shè),景縣網(wǎng)站制作、景縣網(wǎng)頁設(shè)計、景縣網(wǎng)站官網(wǎng)定制、成都微信小程序服務(wù),打造景縣網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供景縣網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
  • 標(biāo)準(zhǔn)庫中有多種順序容器,所有順序容器都提供了快速順序訪問元素的能力,但是這些容器在以下兩方面都有不同的性能折中:① 向容器添加或從容器中刪除元素的代價;② 非順序訪問容器中元素的代價
  • 順序容器類型如下:
  • vector:可變大小數(shù)組。支持快速隨機訪問。在尾部之外的位置插入或刪除元素很慢
  • deque:雙端隊列。支持快速隨機訪問。在頭尾位置插入和刪除速度很快
  • list:雙向鏈表。只支持雙向順序訪問。在list中任何位置進(jìn)行插入和刪除操作速度都很快
  • forward_list:單向鏈表。只支持單向順序訪問。在鏈表中任何位置進(jìn)行插入和刪除操作都很快
  • array:固定大小數(shù)組。支持快速隨機訪問。不能添加或刪除元素。與內(nèi)置數(shù)組相比,array是一種更安全、更易用的數(shù)組類型
  • string:與vector類似,但專門用于保存字符
  • 一般來說,每個容器都定義在一個頭文件中,文件名與類型名相同,即deque定義在頭文件deque中。容器均定義為模板類
  • 所有容器都擁有的操作:
  • 類型別名:①iterator/const_iterator:此容器類型的迭代器類型;②size_type:無符號整數(shù)類型,可保存此容器類型大可能大小;③difference_type:帶符號整數(shù)類型,可保存兩個迭代器之間的距離;④vaule_type:元素類型;⑤reference/const_reference:元素的左值類型
  • 構(gòu)造函數(shù):①C c;:默認(rèn)構(gòu)造函數(shù),構(gòu)造空容器;②C c1(c2);:拷貝構(gòu)造函數(shù);③C c(b,e);將迭代器b和e范圍內(nèi)的元素拷貝到c(array不支持);④C c{x,y,z};:列表初始化
  • 賦值與swap:①c1=c2;;②c={x,y,z};;③c1.swap(c2);;(swap通常比拷貝快得多)④swap(c1,c2);(最好統(tǒng)一使用非成員版本的swap,適用于泛型編程)
  • 大小:①c.size():c中元素數(shù)目(不支持forward_list);②c.max_size():c中可保存的大元素數(shù)目;③c.empty()
  • 添加刪除元素(array不支持,不同容器中這些操作的接口都不同):①c.insert(args);②c.emplace(inits);③c.erase(args);④c.clear()
  • 關(guān)系運算符:①==/!=:所有容器都支持;②</<=/>/>=:無序關(guān)聯(lián)容器不支持
  • 獲取迭代器:c.begin(),c.end()/c.cbegin(),c.cend()
  • 反向容器的額外成員(不支持forward_list):①reverse_iterator/const_reverse_iterator;②c.rbegin(),c.rend()/c.crbegin(),c.crend()
  • 賦值相關(guān)運算會導(dǎo)致指向左邊容器內(nèi)部的迭代器、引用、指針失效。而swap操作將容器內(nèi)容交換不會導(dǎo)致失效(容器類型為array和string除外)
  • 用一個對象來初始化容器時,或?qū)⒁粋€對象插入到容器中時,實際上放入到容器中的是對象值的一個拷貝,而不是對象本身

9.2 順序容器專有操作

  • 初始化(array不可用):①C seq(n);:seq包含n個元素,對這些元素進(jìn)行值初始化,此構(gòu)造函數(shù)是explicit的(string不可用);②C seq(n,t);:seq包含n個初始化為t的元素
  • 賦值(array不適用):①seq.assign(b,e);:將seq中元素替換為迭代器b和e范圍內(nèi)的元素,b和e不能指向seq本身;②seq.assign(il);:將seq中的元素替換為初始化列表il中的元素;③seq.assign(n,t);:將seq中的元素替換為n個值為t的元素
  • 添加元素(array不可用):①c.push_back(t)/c.emplace_back(args):在c的尾部創(chuàng)建一個值為t或由args創(chuàng)建的元素,返回void(forward_list不可用);②c.push_front(t)/c.emplace_front(args):在c的頭部創(chuàng)建一個元素,返回void(vector和string不可用);③c.insert(p,t)/c.emplace(p,args):在迭代器p指向的元素之前創(chuàng)建一個元素,返回指向新添加的元素的迭代器;④c.insert(p,n,t)/c.insert(p,b,e)/c.insert(p,il)
  • 訪問元素(返回的均為引用):①c.back()(forward_list不可用);②c.front();③c[n]/c.at(n)(只能用于string、vector、deque、array)
  • 刪除元素:①c.pop_back():刪除c中尾元素(forward_list不可用);②c.pop_front():刪除c中首元素(vector和string不可用);③c.erase(p):刪除迭代器p所指向元素,返回被刪元素之后元素的迭代器;④c.erase(b,e):刪除迭代器b和e范圍內(nèi)的元素,返回最后一個被刪元素之后元素的迭代器;⑤c.clear():刪除c中所有元素,返回void
  • 改變?nèi)萜鞔笮。孩?code>c.resize(n):調(diào)整c的大小為n個元素,添加的新元素進(jìn)行值初始化,若n小于原長度,則多出的元素被丟棄;②c.resize(n,t):添加的新元素初始化為值t
  • 向一個vector、string、deque插入元素會使所有指向容器的迭代器、引用、指針失效
  • 容器中訪問元素的成員函數(shù)返回的都是引用,如果容器是一個const對象,則返回值是const引用
  • 下標(biāo)運算符并不檢查下標(biāo)是否存在合法范圍內(nèi),使用越界的下標(biāo)是一種嚴(yán)重的設(shè)計錯誤,使用at()成員函數(shù)時如果下標(biāo)越界,會拋出out_of_range異常
  • 刪除deque中除首尾位置之外的任何元素都會使所有迭代器、引用、指針失效。指向vector或string中刪除點之后位置的迭代器、引用、指針都會失效
  • forward_list為單向鏈表,在單向鏈表中,沒有簡單的方法來獲取一個元素的前驅(qū),forward_list并未定義常規(guī)的插入刪除操作,而是定義了名為insert_afteremplace_aftererase_after的操作,并且定義了首前迭代器before_begin,該迭代器允許在鏈表首元素之前添加或刪除元素
  • 如果resize縮小容器,則指向被刪除元素的迭代器、引用、指針都會失效。對vector、string、deque進(jìn)行resize可能導(dǎo)致迭代器、引用、指針失效
  • 如果在一個循環(huán)中插入或刪除deque、string、vector中的元素,不要緩存end返回的迭代器,每次循環(huán)都會重新計算end
  • 當(dāng)容器中元素是連續(xù)存儲,且容器大小可變時,向容器中添加元素必須分配新的內(nèi)存空間來保存已有元素和新元素,vector和string的實現(xiàn)通常會分配比新的空間需求更大的內(nèi)存空間
  • vector和string類型提供了一些成員函數(shù),實現(xiàn)對容器大小的管理操作:①c.capacity():不重新分配內(nèi)存空間的話,c可以保存多少元素;②c.reserve(n):分配至少能容納n個元素的內(nèi)存空間;③c.shrink_to_fit():將能保存的元素空間縮大小減為當(dāng)前的元素個數(shù)

9.3 額外的string操作

  • 構(gòu)造string的其他方法:除通用的構(gòu)造函數(shù)外,string還支持另外三個構(gòu)造函數(shù):①string s(cp,n):s是cp指向數(shù)組中前n個字符的拷貝,此數(shù)組至少包含n個字符;②string s(s2,pos2):s是s2從下標(biāo)pos2開始的字符的拷貝;③string s(s2,pos2,len2):s是s2從下標(biāo)pos2開始len2個字符的拷貝;④s.substr(pos,n):子字符串操作,返回一個string,包含s中從pos開始的n個字符的拷貝
  • 修改string的其他操作:①s,insert(pos,args);②s.erase(pos,len);③s.assign(args);④s.append(args);⑤a.replace(range,args)。其中args可以是下列形式之一:str/str,pos,len/cp,len/cp/n,c/b,e/初始化列表
  • string搜索操作:每個搜索操作都返回一個string::size_type值,表示匹配發(fā)生位置的下標(biāo),如果搜索失敗,則返回一個名為string::npos的static成員,二者均為unsign類型:①s.find(args)/s.rfind(args):查找s中args第一次/最后一次出現(xiàn)的位置;②s.find_first_of(args)/s.find_last_of(args):在s中查找arg中任何一個字符第一次/最后一次出現(xiàn)的位置;③s.find_first_not_of(args)/s.find_last_not_of(args):在s中查找第一個/最后一個不在args中的字符。其中args是以下形式之一:c,pos/s2,pos/cp,pos/cp,pos,n
  • 除了關(guān)系運算符外,標(biāo)準(zhǔn)庫string類型還提供了一組compare函數(shù),與C標(biāo)準(zhǔn)庫的strcmp函數(shù)類型,根據(jù)s是等于、大于、小于參數(shù)指定的字符串,返回0、正數(shù)、負(fù)數(shù),s.compare(args)的參數(shù)形式有:s2/pos1,n1,s2/pos1,n1,s2,pos2,n2/cp/pos1,n1,cp/pos1,n1,cp,n2
  • 字符串中常常包含表示數(shù)值的字符,新標(biāo)準(zhǔn)引入了多個函數(shù),可以實現(xiàn)數(shù)值數(shù)據(jù)與string之間的轉(zhuǎn)換:①to_string(val):將數(shù)值類型轉(zhuǎn)為string;②stoi(s,p,b)/stol(s,p,b)/stoul(s,p,b)/stoll(s,p,b)/stoull(s,p,b):將s轉(zhuǎn)為整型,b表示轉(zhuǎn)換用的基數(shù),默認(rèn)為10,p是size_t指針,用來保存s中第一個非數(shù)值字符的下標(biāo),默認(rèn)為0,即不保存下標(biāo);③stof(s,p)/stod(s,p)/stold(s,p):將s轉(zhuǎn)為浮點型

9.4 容器適配器

  • 除了順序容器外,標(biāo)準(zhǔn)庫還定義了三個順序容器適配器:stack、queue、priority_queue,本質(zhì)上一個容器適配器是一種機制,能使某種事物的行為看起來像另外一種事物,如stack適配器接受一個順序容器,使其操作起來像一個stack一樣
  • 每個適配器都定義兩個構(gòu)造函數(shù):默認(rèn)構(gòu)造函數(shù)創(chuàng)建一個空對象,接受一個容器的構(gòu)造函數(shù)拷貝該容器來初始化適配器,如stackstk(seq);,默認(rèn)情況下stack和queue是基于deque實現(xiàn)的,可以在創(chuàng)建一個適配器時將一個命名的順序容器作為第二個類型參數(shù),來重載默認(rèn)容器類型stack>str_stk;
  • 所有適配器都要求容器具有添加、刪除、訪問尾元素元素的能力,因此適配器不能構(gòu)造在array和forward_list上。stack可以用除上述兩種外的任意容器類型來構(gòu)造,queue不能基于vector構(gòu)造,priority_queue不能基于list構(gòu)造。可通過適配器的container_type類型訪問底層容器類型
  • 棧操作:①s.pop();②s.push(item)/s.emplace(args):③s.top()
  • 隊列操作:①q.pop();②q.front();③q.back()(只能用于queue);④q.top()(只能用于priority_queue);⑤q.push(item)/q.emplace(args)
10. 泛型算法

10.1 泛型算法概述

  • 標(biāo)準(zhǔn)庫并沒有給容器定義大量的操作,而是提供了一組算法,這些算法大多數(shù)都獨立于任何容器,稱這些算法為泛型的,可用于不同類型的容器和不同類型的元素
  • 大多數(shù)算法都定義在頭文件中,還有一組數(shù)值泛型算法定義在頭文件中。一般情況下,這些算法并不直接操作容器,而是遍歷由兩個迭代器指定的一個元素范圍來進(jìn)行操作,如auto result=find(vec.cbegin(),vec.cend(),val);,如果發(fā)現(xiàn)匹配元素,則返回指向該元素的迭代器,否則返回尾后迭代器
  • 標(biāo)準(zhǔn)庫提供了超過100個算法,大多數(shù)算法遍歷輸入范圍的方式相似,但它們使用范圍中元素的方式不同,理解算法最基本的方法就是了解它們是否:讀取元素、改變元素、重排元素順序
  • 只讀算法:find()函數(shù)和count()函數(shù)都是只讀算法,定義在頭文件中的accumulate()函數(shù)也是只讀算法,equal(r1.cbegin(),r1.cend(),r2.cbegin())函數(shù)用于比較兩個序列是否保存相同的值,該函數(shù)接受三個迭代器,前兩個表示第一個序列的范圍,第三個表示第二個序列的首元素,這種只接受一個單一迭代器來表示第二個序列的算法,都假定第二個序列至少與第一個序列一樣長
  • 寫容器元素的算法:①fill(vec.begin(),vec.end(),10)向給定序列中寫入數(shù)據(jù);②fill_n(vec.begin(),n,0):必須保證vec至少包含n個元素/fill_n(back_inserter(vec),n,0):使用插入迭代器back_inserter會調(diào)用push_back來添加元素;③copy(bigin(a1),end(a1),a2):把a1的內(nèi)容拷貝給a2;④replace(ilst.cbegin(),ilst.cend(),0,10):將序列中所有0替換為10/replace_copy(ilst.cbegin(),ilst.cend(),back_inserter(ivec),0,10):ilst不變,ilst中0替換為10后拷貝到ivec中
  • 重排容器元素的算法:①sort():排序;②unique():去除相鄰重復(fù)項;以下步驟消除vector中的重復(fù)單詞
sort(v.begin(),v.end());	//排序
auto end_unique = unique(v.begin(),v.end());	//unique函數(shù)實現(xiàn)無重復(fù)排列,返回指向不重復(fù)區(qū)域的尾后迭代器
v.erase(end_unique,v.end());	//刪除重復(fù)單詞

10.2 定制操作

  • 很多算法都會比較輸入序列中的元素,默認(rèn)情況下,這類算法使用元素類型的<=運算符來比較。標(biāo)準(zhǔn)庫還為這些算法提供了額外的版本,使得能夠用自己定義的操作來代替默認(rèn)運算符
  • 謂詞是一個可調(diào)用的表達(dá)式,其返回結(jié)果是一個能用作條件的值,標(biāo)準(zhǔn)庫算法所使用的謂詞分為一元謂詞(接受一個參數(shù))和二元謂詞(接受兩個參數(shù))。接受謂詞參數(shù)的算法對輸入序列中的元素調(diào)用謂詞,元素類型必須能轉(zhuǎn)換為謂詞的參數(shù)類型
  • 接受一個二元謂詞參數(shù)的sort()函數(shù)用謂詞代替<來比較元素,如sort(words.begin(),words.end(),isShorter),若想要保證穩(wěn)定排序,可使用stable_sort()函數(shù)
  • 可以向一個算法傳遞任何類別的可調(diào)用對象,對于一個對象或表達(dá)式,如果可以對其使用調(diào)用運算符,則稱它為可調(diào)用的。可調(diào)用對象包括:函數(shù)、函數(shù)指針、重載了函數(shù)調(diào)用運算符的類、lambda表達(dá)式
  • 一個lambda表達(dá)式表示一個可調(diào)用的代碼單元,可以將其理解為一個未命名的內(nèi)聯(lián)函數(shù),與函數(shù)類似,一個lambda具有一個返回類型、一個參數(shù)列表、一個函數(shù)體。但與函數(shù)不同,lambda可能定義在函數(shù)內(nèi)部
  • 一個lambda表達(dá)式具有以下形式:

[capture list] (parameter list) ->return type {function body}

其中,捕獲列表是一個lambda所在函數(shù)中定義的局部變量的列表,通常為空,參數(shù)列表、返回類型、函數(shù)體與普通函數(shù)一樣,但是lambda必須使用尾置返回來指定返回類型。lambda可以忽略參數(shù)列表和返回類型,但必須包含捕獲列表和函數(shù)體:auto f = []{return 10;};,忽略參數(shù)列表即參數(shù)列表為空,忽略返回類型則從函數(shù)體代碼中推斷返回類型,若函數(shù)體中包含單一return之外的內(nèi)容且未指定返回類型,則返回void

  • lambda不能有默認(rèn)參數(shù),實參數(shù)目永遠(yuǎn)與形參數(shù)目相等,空捕獲列表說明此lambda不使用它所在函數(shù)中的任何局部變量,lambda使用示例如下:
//將words按長度穩(wěn)定排序
stable_sort(words.begin(),words.end(),[](const string &a,const string &b){return a.size()return a.size()>=sz;});
//從wc迭代器開始打印單詞,每個單詞后接一個空格
for_each(wc,words.end(),[](const string &s){cout<
  • 當(dāng)定義一個lambda時,編譯器生成一個與lambda對應(yīng)的新的類類型
  • 類似于參數(shù)傳遞,變量的捕獲方式也可以是值捕獲([a])或引用捕獲[&a],采用值捕獲的前提是變量可以拷貝,被值捕獲的變量是在lambda創(chuàng)建時拷貝,而非調(diào)用時,因此隨后對其的修改不會影響到lambda內(nèi)對應(yīng)的值,當(dāng)以引用方式捕獲一個變量時,必須保證在lambda執(zhí)行時變量是存在的
  • 除了顯式列出希望使用的來自所在函數(shù)的變量之外,還可以讓編譯器根據(jù)lambda體中的代碼來推斷要使用哪些變量,此時應(yīng)在捕獲列表中寫一個[&][=],&告訴編譯器采用引用捕獲方式,=采用值捕獲方式。當(dāng)混用隱式捕獲和顯式捕獲時,捕獲列表中第一個元素必須是&或=
  • 默認(rèn)情況下,對于一個值被拷貝的變量,lambda不會改變其值,如果希望能改變一個被捕獲的變量的值,必須在參數(shù)列表首加上關(guān)鍵字mutable:auto f=[v]()mutable{return ++v;};,一個引用捕獲的變量是否可以修改依賴于該引用指向的是一個const類型還是非const類型
  • 對于捕獲列表為空的lambda,通常可以用函數(shù)來代替,對捕獲局部變量的lambda,需要使用標(biāo)準(zhǔn)庫中的bind()函數(shù),該函數(shù)定義在頭文件中,可以將bind函數(shù)看作一個通用的函數(shù)適配器,接受一個可調(diào)用對象,生成一個新的可調(diào)用對象auto newCallable = bind(callable,arg_list);,當(dāng)調(diào)用newCallable時,會調(diào)用callable,并傳給它arg_list中的參數(shù),arg_list是一個逗號分隔的參數(shù)列表,其中形如_n的參數(shù)代表占位符,綁定引用參數(shù)時要使用ref()cref()函數(shù):bind(print,ref(os),_1,' ')

10.3 再探迭代器

  • 除了每個容器自己的迭代器之外,標(biāo)準(zhǔn)庫在頭文件中還定義了額外幾種迭代器,包括:插入迭代器、流迭代器、反向迭代器、移動迭代器
  • 插入迭代器是一種迭代器適配器,它接受一個容器,生成一個迭代器,能實現(xiàn)向給定容器添加元素。插入器有三種類型:①back_inserter(c)創(chuàng)建一個使用c.push_back(t)的迭代器;②front_inserter(c)創(chuàng)建一個使用c.push_front(c)的迭代器;③inserter(c,iter)創(chuàng)建一個使用c.insert(iter,t)的迭代器。使用插入器時,只需要iter=t;即可在iter指定的位置處插入值t
  • 流迭代器可以用泛型算法從流對象讀取數(shù)據(jù)及寫入數(shù)據(jù),istream_iterator讀取輸入流,ostream_iterator向一個輸出流寫數(shù)據(jù)
istream_iteratorin(is);	//in從輸入流is讀取類型為T的值
istream_iteratorend;	//讀取類型為T的尾后迭代器
ostream_iteratorout(os);	//out將類型為T的值寫到輸出流os中
ostream_iteratorout(os,d);	//out將類型為T的值寫到輸出流os中,且每個值后都輸出一個d,d為C風(fēng)格的字符串
  • 反向迭代器就是在容器中從尾元素向首元素反向移動的迭代器,++it會移動到前一個元素,–it會移動到下一個元素,除了forward_list之外,其他容器都支持反向迭代器,可以通過調(diào)用rbegin(),rend(),crbegin(),crend()成員函數(shù)來獲得反向迭代器,反向迭代器調(diào)用base()成員函數(shù)可以得到正向迭代器,但是指向的元素不同(正向迭代器指向后一個元素)

10.4 泛型算法結(jié)構(gòu)

  • 任何算法的最基本特性是它要求其迭代器提供哪些操作,算法所要求的迭代器操作可分為5個迭代器類別:
  1. 輸入迭代器:只讀,不寫,單遍掃描,只能遞增;
  2. 輸出迭代器:只寫,不讀,單遍掃描,只能遞增;
  3. 前向迭代器:可讀寫,多遍掃描,只能遞增;
  4. 雙向迭代器:可讀寫,多遍掃描,可遞增遞減;
  5. 隨機訪問迭代器:可讀寫,多遍掃描,支持全部迭代器運算
  • 迭代器也定義了一組公共操作,一些操作所有迭代器都支持,另外一些只有特定迭代器才支持,除了輸出迭代器之外,一個高層的迭代器支持低層迭代器的所有操作,各迭代器需要支持的操作包括:
  1. 輸入迭代器:① 用于比較兩個迭代器的相等==和不相等運算符!=;② 迭代器的前置和后置遞增運算++;③ 用于讀取元素的解引用運算符*(只會出現(xiàn)在賦值運算符的右側(cè));④ 用于解引用迭代器并提取成員的箭頭運算符->
  2. 輸出迭代器:與1類似,解引用運算符只能出現(xiàn)在賦值運算符的左側(cè)
  3. 前向迭代器:1和2會破環(huán)迭代器原本結(jié)構(gòu),只能單遍掃描,前向迭代器可以保存當(dāng)前狀態(tài),多次讀寫同一個元素
  4. 雙向迭代器:還支持前置和后置的遞減運算符--
  5. 隨機訪問迭代器:還支持 ① 用于比較兩個迭代器相對位置的關(guān)系運算符<,<=,>,>=;② 迭代器和一個整數(shù)值的加減運算+,+=,-,-=;③ 用于兩個迭代器的減法運算-;④ 下標(biāo)運算符iter[n],*iter[n](兩者等價)
  • 大多數(shù)算法的形參模式是下列4仲形式之一:其中dest參數(shù)是一個表示算法可以寫入的目的位置的迭代器,常被用于綁定到一個插入迭代器或是一個ostream_iterator
alg(beg,end,other args);
alg(beg,end,dest,other args);
alg(beg,end,beg2,other args);
alg(beg,end,beg2,end2,other args);
  • 算法命名規(guī)范:① 一些算法使用重載形式傳遞一個謂詞,來代替<==;② 接受一個元素值的算法通常會有一個不同名的后綴加上_if的版本,該版本接受一個謂詞代替元素值,如findfind_if;③ 默認(rèn)情況下,重排元素的算法將重排后的元素寫回給定的輸入序列中,通常提供額外的拷貝版本,加上后綴_copy,如reversereverse_copy
  • 與其他容器不同,鏈表類型list和forward_list定義了幾個成員函數(shù)形式的算法,特別定義了獨有的sort(),merge(),remove(),reverse(),unique()算法,通用版本的sort要求隨機訪問迭代器,因此不能用于鏈表類型
11. 關(guān)聯(lián)容器

11.1 關(guān)聯(lián)容器概述

  • 關(guān)聯(lián)容器中的元素是按關(guān)鍵字來保存和訪問的,兩個主要的關(guān)聯(lián)容器類型是mapset,標(biāo)準(zhǔn)庫提供8個關(guān)聯(lián)容器,其不同體現(xiàn)在3個維度上:① set或map;② 是否允許重復(fù)的關(guān)鍵字,允許重復(fù)關(guān)鍵字的容器以multi開頭;③ 是否按順序保存元素,不按關(guān)鍵字順序存儲的容器以unordered_開頭
  • map和multimap定義在頭文件中,set和multiset定義在頭文件中,unordered_multimapunordered_multiset定義在頭文件
  • 關(guān)聯(lián)容器對其關(guān)鍵字類型有限制,有序容器的關(guān)鍵字類型必須定義元素比較的方法,默認(rèn)情況下標(biāo)準(zhǔn)庫使用<運算符來比較兩個關(guān)鍵字
  • 頭文件中,定義了名為pair的標(biāo)準(zhǔn)庫類型,一個pair保存兩個數(shù)據(jù)成員,當(dāng)創(chuàng)建一個pair時,必須提供兩個類型名,pair的默認(rèn)構(gòu)造函數(shù)對數(shù)據(jù)成員進(jìn)行值初始化,map中的元素是pair,標(biāo)準(zhǔn)庫中的pair操作包括:①pairp;②pairp(v1,v2);③make_pair(v1,v2);④p.firstp.second

11.2 關(guān)聯(lián)容器操作

  • 關(guān)聯(lián)容器還定義了3仲類型:①key_value:關(guān)鍵字類型;②mapped_type:map的值類型;③value_type:對于set為關(guān)鍵字類型,對于map為pair
  • 當(dāng)解引用一個關(guān)聯(lián)容i去迭代器時,會得到一個類型為容器的value_type的值的引用。對map而言,會返回一個pair類型,其first成員保存const關(guān)鍵字,不能修改,second成員保存值,可以修改;對set而言,會返回const關(guān)鍵字,不能修改。當(dāng)使用一個迭代器遍歷一個有序關(guān)聯(lián)容器時,迭代器按關(guān)鍵字升序遍歷元素
  • 遍歷關(guān)聯(lián)容器:
auto m_it = m.cbegin();
while(m_it != m.cend()){cout<< m_it->first<< ":"<< m_it->second<< endl;
	++m_it;
}
  • 關(guān)聯(lián)容器的insert()成員向容器中添加一個元素或一個元素范圍,由于map和set包含不重復(fù)的關(guān)鍵字,因此插入一個已存在的元素對容器沒有任何影響:①c.insert(v)/c.emplace(args):v為value_type類型的對象,args用來構(gòu)造一個元素;②c.insert(b,e)/c.insert(il):b和e是迭代器,il是花括號列表;③c.insert(p,v)/c.emplace(p,args):將迭代器p作為一個提示,指出從哪里開始搜索新元素應(yīng)該存儲的位置。對于不包括重復(fù)關(guān)鍵字的容器,添加單一元素的insert和emplace返回一個pair,pair的first成員是一個迭代器,指向具有給定關(guān)鍵字的元素,second成員是一個bool值,指出元素是插入成功還是已存在于容器中
  • 從關(guān)聯(lián)容器中刪除元素:①c.erase(k):從c中刪除每個關(guān)鍵字為k的元素,返回刪除元素的數(shù)量;②c.erase(p):從c中刪除迭代器p指定的元素,返回一個p之后的迭代器;③c.erase(b.e):刪除迭代器b和e范圍中的元素,返回e
  • map和unordered_map容器提供了下標(biāo)運算符和一個對應(yīng)的at函數(shù),set、multimap、unordered_multimap不支持下標(biāo):①c[k]:返回關(guān)鍵字為k的元素,若k不在c中,添加一個關(guān)鍵字為k的元素,對其進(jìn)行值初始化;②c.at(k):訪問關(guān)鍵字為k的元素,若k不在c中,拋出一個out_of_range異常
  • 在一個關(guān)聯(lián)容器中查找元素:①c.find(k):返回一個迭代器,指向第一個關(guān)鍵字為k的元素,若k不在容器中,則返回尾后迭代器;②c.count(k):返回關(guān)鍵字等于k的元素的數(shù)量;③c.lower_bound(k):返回一個迭代器,指向第一個關(guān)鍵字不小于k的元素(不適用于無序容器);④c.upper_bound(k):返回一個迭代器,指向第一個關(guān)鍵字大于k的元素(可與上一個函數(shù)一起給定在multimap或multiset中某個關(guān)鍵字對應(yīng)的迭代器范圍);⑤c.equal_range(k):返回一個迭代器pair,表示關(guān)鍵字等于k的元素的范圍,若k不存在,pair兩個成員均等于c.end()
  • 無序容器:新標(biāo)準(zhǔn)定義了4個無序關(guān)聯(lián)容器,這些容器不使用比較運算符來組織元素,而是使用一個哈希函數(shù)和關(guān)鍵字類型的==運算符。無序容器在存儲上組織為一組桶,每個桶保存零個或多個元素,使用一個哈希函數(shù)將元素映射到桶。如果容器允許重復(fù)關(guān)鍵字,所有具有相同關(guān)鍵字的元素都會在同一個桶中,因此無序容器的性能依賴于哈希函數(shù)的質(zhì)量和桶的數(shù)量和大小。理想情況下,哈希函數(shù)會將每個特定的值映射到唯一的桶,但是將不同關(guān)鍵字的元素映射到相同的桶也是允許的,當(dāng)一個桶保存多個元素時,需要順序搜索這些元素來查找想要的那個
12. 動態(tài)內(nèi)存

12.1 對象與內(nèi)存分配關(guān)系

  • 程序中所使用的對象都有嚴(yán)格定義的生存期,全局對象在程序啟動時分配,在 程序結(jié)束時銷毀;局部自動對象在進(jìn)入其定義所在程序塊時被創(chuàng)建,在離開塊時銷毀;局部static對象在第一次使用前分配,在程序結(jié)束時銷毀。除了自動和static對象外,C++還支持動態(tài)分配對象,動態(tài)分配的對象的生存期與它們在哪里創(chuàng)建是無關(guān)的,只有當(dāng)顯式地被釋放時,這些對象才會銷毀
  • 動態(tài)對象地正確釋放是及其容器出錯地地方,為了更安全地使用動態(tài)對象,標(biāo)準(zhǔn)庫定義了兩個智能指針類型來管理動態(tài)分配的對象,當(dāng)一個對象應(yīng)該被釋放時,指向它的智能指針可以確保自動地釋放它
  • 靜態(tài)內(nèi)存用來保存局部static對象、類static數(shù)據(jù)成員、定義在任何函數(shù)之外的變量,棧內(nèi)存用來保存定義在函數(shù)內(nèi)的非static對象。分配在靜態(tài)或棧內(nèi)存中的對象由編譯器自動創(chuàng)建和銷毀,棧對象僅在其定義的程序塊運行時才存在,static對象在使用前分配,程序結(jié)束時銷毀。除了靜態(tài)內(nèi)存和棧內(nèi)存,每個程序還有一個內(nèi)存池,這部分內(nèi)存被稱為自由空間或堆,程序用堆來存儲動態(tài)分配的對象

12.2 動態(tài)內(nèi)存與智能指針

  • 在C++中,動態(tài)內(nèi)存的管理是通過一對運算符來完成的:①new:在動態(tài)內(nèi)存中為對象分配空間并返回一個指向該對象的指針;②delete:接受一個動態(tài)對象的指針,銷毀該對象并釋放與之關(guān)聯(lián)的內(nèi)存
  • 為了更容易也更安全地使用動態(tài)內(nèi)存,新的標(biāo)準(zhǔn)庫提供了兩種智能指針類型來管理動態(tài)對象,智能指針負(fù)責(zé)自動釋放所指向地對象,這兩種智能指針地區(qū)別在于管理底層指針的方式:①shared_ptr:允許多個指針指向同一個對象;②unique_ptr:獨占所指向的對象。標(biāo)準(zhǔn)庫還定義了一個名為weak_ptr的伴隨類,它是一種弱引用,指向shared_ptr所管理的對象,這三種類型都定義在頭文件中
  • 智能指針也是模板,創(chuàng)建一個智能指針時,必須提供指針可以指向的類型,默認(rèn)初始化的智能指針中保存著一個空指針:shared_ptrp1;,智能指針的使用方法與普通指針類似,解引用一個智能指針返回它指向的對象,如果在一個條件判斷中使用智能指針,就是檢測它是否為空
  • shared_ptr和unique_ptr都支持的操作有:①shared_ptrsp/unique_ptrup:空智能指針;②p.get():返回p中保存的指針,要小心使用,若智能指針釋放了其對象,返回的指針?biāo)赶虻膶ο笠簿拖Я耍虎?code>swap(p,q)/p.swap(q):交換p和q中的指針
  • shared_ptr獨有的操作:①make_shared(args):返回一個指向類型T對象的智能指針,使用args初始化此對象;②sharedp(q):p是q的拷貝,此操作會遞增q中的計數(shù)器,q中的指針必須能轉(zhuǎn)換為T*;③p = q:p和q所保存的指針必須能相互轉(zhuǎn)換,此操作會遞減p的引用計數(shù),遞增q的引用計數(shù),若p的引用計數(shù)變?yōu)?,則將其管理的原內(nèi)存釋放;④p.use_count():返回與p共享對象的智能指針對象,該操作很慢,主要用于調(diào)試;⑤p.unique():若p.use_count()為1,返回true,否則返回false
  • 可以認(rèn)為每個shared_ptr都有一個關(guān)聯(lián)的計數(shù)器,稱之為引用計數(shù),當(dāng)拷貝一個shared_ptr時,計數(shù)器會遞增,當(dāng)為shared_ptr賦予一個新值或shared_ptr被銷毀(如局部shared_ptr離開其作用域)時,計數(shù)器就會遞減。用哪種數(shù)據(jù)結(jié)構(gòu)來記錄有多少指針共享對象,完全由標(biāo)準(zhǔn)庫的具體實現(xiàn)來決定
  • shared_ptr的析構(gòu)函數(shù)會遞減它所指向的對象的引用計數(shù),如果引用計數(shù)變?yōu)?,shared_ptr的析構(gòu)函數(shù)就會銷毀對象,并釋放它所占用的內(nèi)存
  • 默認(rèn)情況下,動態(tài)分配的對象是默認(rèn)初始化的:int *p = new int;,*p的值未定義,在類型名后跟一對括號即可對動態(tài)分配的對象進(jìn)行值初始化:int *p = new int();:*p的值為0
  • 如果提供了一個括號包圍的初始化器,就可以使用auto從該初始化器來推斷想要分配的對象的類型:auto p = new auto(obj);,p指向一個與obj類型相同的對象,該對象用obj進(jìn)行初始化,當(dāng)且僅當(dāng)括號中有單一初始化器時才可使用auto
  • 類似于其他任何const對象,一個動態(tài)分配的const對象必須進(jìn)行初始化,對于一個定義了默認(rèn)構(gòu)造函數(shù)的類類型,其const動態(tài)對象可以隱式初始化,而其他類型的對象必須顯式初始化:const int *p = new const int(10);,new返回的指針是一個指向const的指針
  • 若一個程序用光了它所有可用的內(nèi)存,new表達(dá)式就會失敗,默認(rèn)情況下,如果new不能分配所要求的內(nèi)存空間,就會拋出一個類型為bad_alloc的異常,可通過int* p = new (nothrow) int;的方式阻止拋出異常,這種形式的new稱為定位new

12.3 智能指針的使用

  • 若不初始化一個智能指針,它就會被初始化為一個空指針,還可以使用new返回的指針來初始化智能指針:shared_ptrp(new int(10));,接受指針參數(shù)的智能指針構(gòu)造函數(shù)是explicit的,因此不能將一個內(nèi)置指針隱式轉(zhuǎn)換為一個智能指針,必須使用直接初始化的形式
  • 定義和改變shared_ptr的方法:①shared_ptrp(q):p管理內(nèi)置指針q所指向的對象,q必須指向new分配的內(nèi)存,且能偶轉(zhuǎn)換為T*類型;②shared_ptrp(u):p從unique_ptr u那里接管了對象的所有權(quán),將u置為空;③shared_ptrp(q,d):p使用可調(diào)用對象d來代替delete;④shared_ptrp(p2,d):p是shared_ptr p2的拷貝;⑤p.reset()/p.reset(q)/p.reset(q,d):若p是唯一指向其對象的shared_ptr,reset會釋放此對象,并將p置為空;若傳遞了參數(shù)內(nèi)置指針q,會令p指向q;若還傳遞了參數(shù)d,會調(diào)用d來代替delete
  • 注意事項:① 不要混用普通指針和智能指針:當(dāng)將一個shared_ptr綁定到一個普通指針時,就將內(nèi)存的管理責(zé)任交給了這個shared_ptr,此時就不該再使用內(nèi)置指針來訪為shared_ptr所指向的內(nèi)存了,因為無法知道對象何時會被銷毀;② 不要使用get()初始化另一個智能指針或為智能指針賦值:這樣做會導(dǎo)致內(nèi)存被二次delete,get()只有在確定代碼不會delete指針的情況下使用
  • 有些沒有定義析構(gòu)函數(shù)的類,需要用戶顯式地釋放所使用地資源,如果忘記釋放資源或在釋放之前放生了異常,程序會發(fā)生資源泄露。可以將釋放資源的函數(shù)作為刪除器與原對象一起傳入智能指針:shared_ptrp(&con,disconnection);,此時資源會自動釋放
  • 與shared_ptr不同,某個時刻只能有一個unique_ptr指向一個給定對象,當(dāng)unique_ptr被銷毀時,它所指向的對象也被銷毀。unique_ptr沒有類似make_shared的標(biāo)準(zhǔn)庫函數(shù),必須將其綁定在一個new返回的指針上,unique_ptr不支持普通的拷貝或賦值
  • unique_ptr操作:①unique_ptru(d):創(chuàng)建一個空unique_ptr,指向類型為T的對象,用類型為D的對象d代替delete;②u.release():放棄對指針的控制權(quán),將u置為空并返回指針;③u.reset()/u.reset(q)/u.reset(nullptr):釋放u指向的對象,如果提供了內(nèi)置指針q,令u指向這個對象,否則將u置為空
  • 可以通過調(diào)用release或reset將指針的所有權(quán)從一個非const的unique_ptr轉(zhuǎn)移給另一個unique_ptr:unique_ptrp2(p1.release())/p2.reset(p1.release())。直接使用release并不會釋放內(nèi)存,而且會丟失指針。可以拷貝或賦值一個將要被銷毀的unique_ptr,如從函數(shù)返回一個unique_ptr。重載一個unique_ptr的刪除器必須在尖括號中提供刪除器類型:unique_ptrp(&con,disconnection);
  • weak_ptr是一種不控制所指向?qū)ο笊嫫诘闹悄苤羔槪赶蛴梢粋€shared_ptr管理的對象,綁定weak_ptr不會改變shared_ptr的引用計數(shù),一旦最后一個指向?qū)ο蟮膕hared_ptr被銷毀,對象就會被釋放,無論還有沒有weak_ptr指向它
  • weak_ptr操作:①weak_ptrw(sp)/w = sp:將w指向shared_ptr指針sp指向的對象;②w.reset():將w置為空;③w.use_count():與w共享的shared_ptr的數(shù)量;④w.expired():若w.use_count()為0,返回true,否則返回false;⑤w.lock():若w.expired()為true,返回一個空shared_ptr,否則返回一個指向w的對象的shared_ptr

12.4 動態(tài)數(shù)組

  • new和delete運算符一次分配和釋放一個對象,C++和標(biāo)準(zhǔn)庫還提供了兩種一次分配一個對象數(shù)組的方法:① C++定義了另一種new表達(dá)式語法,可以分配并初始化一個對象數(shù)組;② 標(biāo)準(zhǔn)庫中包含了一個名為allocator的類,可以將分配和初始化分離。大多數(shù)應(yīng)用都沒有直接訪問動態(tài)數(shù)組的需求,使用標(biāo)準(zhǔn)庫容器會更加簡單和快速
  • 使用new分配動態(tài)數(shù)組時,要指明分配的對象的數(shù)目:int *p = new int[10];,此時會得到一個元素類型的指針(動態(tài)數(shù)組并不是數(shù)組類型),由于分配的內(nèi)存并不是一個數(shù)組類型,因此不能對動態(tài)數(shù)組調(diào)用begin或end。new分配的對象,無論是單個分配還是數(shù)組中的都是默認(rèn)初始化的,加上空括號后變?yōu)橹党跏蓟?code>int *p = new int[10]();,釋放動態(tài)數(shù)組:delete [] p;
  • 標(biāo)準(zhǔn)庫提供了一個可以管理new分配的數(shù)組的unique_ptr版本:unique_ptrp(new int[]10);,可以使用下標(biāo)運算符來訪問數(shù)組中的元素。與unique_ptr不同,shared_ptr不直接支持管理動態(tài)數(shù)組,如果要使用shared_ptr管理,必須提供自定義的刪除器shared_ptrp(new int[10],[](int *p){delete[] p});,并且不能使用下標(biāo)運算符,只能用gert()獲取內(nèi)置指針后再訪問數(shù)組元素
  • new將內(nèi)存分配和對象構(gòu)造結(jié)合在了一起,delete將對象析構(gòu)和內(nèi)存釋放結(jié)合在了一起,這樣在分配少量對象時方便使用,但是當(dāng)要分配大量內(nèi)存時,希望將內(nèi)存分配和對象構(gòu)造分離。標(biāo)準(zhǔn)庫allocator定義在頭文件中,提供了一種類型感知的內(nèi)存分配方法,分配的內(nèi)存是未構(gòu)造的
  • allocator類算法:①allocatora:定義一個可以為類型T分配內(nèi)存的allocator對象;②a.allocator(n):分配一段可以保存n個類型為T的對象的未構(gòu)造的內(nèi)存;③a.deallocator(p,n):釋放從T*指針p開始的n個T類型對象的內(nèi)存,p必須分配過n個T類型對象,且已被創(chuàng)建的對象必須調(diào)用過destroy;④a.construct(p,args):在p指向的未構(gòu)造內(nèi)存中通過args構(gòu)造一個對象;⑤a.destory(p):對p指向的對象執(zhí)行析構(gòu)函數(shù);⑥uninitialized_copy(b,e,b2)/uninitialized_copy_n(b,n,b2):將迭代器b到e中的元素拷貝到迭代器b2指向的未構(gòu)造內(nèi)存中,b2的內(nèi)存必須足夠大;⑦uninitialized_fill(b,e,t)/uninitialized_fill_n(b,n,t):在迭代器b到e的未構(gòu)造內(nèi)存中放入值為t的拷貝

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前題目:【C++基礎(chǔ)】2.標(biāo)準(zhǔn)庫-創(chuàng)新互聯(lián)
鏈接URL:http://vcdvsql.cn/article12/dsdpdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站做網(wǎng)站品牌網(wǎng)站設(shè)計App設(shè)計全網(wǎng)營銷推廣手機網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)