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

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

9.1 順序容器概述

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

9.2 順序容器專有操作

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

9.3 額外的string操作

  • 構(gòu)造string的其他方法:除通用的構(gòu)造函數(shù)外,string還支持另外三個(gè)構(gòu)造函數(shù):①string s(cp,n):s是cp指向數(shù)組中前n個(gè)字符的拷貝,此數(shù)組至少包含n個(gè)字符;②string s(s2,pos2):s是s2從下標(biāo)pos2開始的字符的拷貝;③string s(s2,pos2,len2):s是s2從下標(biāo)pos2開始len2個(gè)字符的拷貝;④s.substr(pos,n):子字符串操作,返回一個(gè)string,包含s中從pos開始的n個(gè)字符的拷貝
  • 修改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搜索操作:每個(gè)搜索操作都返回一個(gè)string::size_type值,表示匹配發(fā)生位置的下標(biāo),如果搜索失敗,則返回一個(gè)名為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中任何一個(gè)字符第一次/最后一次出現(xiàn)的位置;③s.find_first_not_of(args)/s.find_last_not_of(args):在s中查找第一個(gè)/最后一個(gè)不在args中的字符。其中args是以下形式之一:c,pos/s2,pos/cp,pos/cp,pos,n
  • 除了關(guān)系運(yùn)算符外,標(biāo)準(zhǔn)庫(kù)string類型還提供了一組compare函數(shù),與C標(biāo)準(zhǔn)庫(kù)的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)引入了多個(gè)函數(shù),可以實(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中第一個(gè)非數(shù)值字符的下標(biāo),默認(rèn)為0,即不保存下標(biāo);③stof(s,p)/stod(s,p)/stold(s,p):將s轉(zhuǎn)為浮點(diǎn)型

9.4 容器適配器

  • 除了順序容器外,標(biāo)準(zhǔn)庫(kù)還定義了三個(gè)順序容器適配器:stack、queue、priority_queue,本質(zhì)上一個(gè)容器適配器是一種機(jī)制,能使某種事物的行為看起來像另外一種事物,如stack適配器接受一個(gè)順序容器,使其操作起來像一個(gè)stack一樣
  • 每個(gè)適配器都定義兩個(gè)構(gòu)造函數(shù):默認(rèn)構(gòu)造函數(shù)創(chuàng)建一個(gè)空對(duì)象,接受一個(gè)容器的構(gòu)造函數(shù)拷貝該容器來初始化適配器,如stackstk(seq);,默認(rèn)情況下stack和queue是基于deque實(shí)現(xiàn)的,可以在創(chuàng)建一個(gè)適配器時(shí)將一個(gè)命名的順序容器作為第二個(gè)類型參數(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()
  • 隊(duì)列操作:①q.pop();②q.front();③q.back()(只能用于queue);④q.top()(只能用于priority_queue);⑤q.push(item)/q.emplace(args)
10. 泛型算法

10.1 泛型算法概述

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

10.2 定制操作

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

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

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

10.3 再探迭代器

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

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

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

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

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

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

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

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

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

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

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

12.3 智能指針的使用

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

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

  • new和delete運(yùn)算符一次分配和釋放一個(gè)對(duì)象,C++和標(biāo)準(zhǔn)庫(kù)還提供了兩種一次分配一個(gè)對(duì)象數(shù)組的方法:① C++定義了另一種new表達(dá)式語(yǔ)法,可以分配并初始化一個(gè)對(duì)象數(shù)組;② 標(biāo)準(zhǔn)庫(kù)中包含了一個(gè)名為allocator的類,可以將分配和初始化分離。大多數(shù)應(yīng)用都沒有直接訪問動(dòng)態(tài)數(shù)組的需求,使用標(biāo)準(zhǔn)庫(kù)容器會(huì)更加簡(jiǎn)單和快速
  • 使用new分配動(dòng)態(tài)數(shù)組時(shí),要指明分配的對(duì)象的數(shù)目:int *p = new int[10];,此時(shí)會(huì)得到一個(gè)元素類型的指針(動(dòng)態(tài)數(shù)組并不是數(shù)組類型),由于分配的內(nèi)存并不是一個(gè)數(shù)組類型,因此不能對(duì)動(dòng)態(tài)數(shù)組調(diào)用begin或end。new分配的對(duì)象,無論是單個(gè)分配還是數(shù)組中的都是默認(rèn)初始化的,加上空括號(hào)后變?yōu)橹党跏蓟?code>int *p = new int[10]();,釋放動(dòng)態(tài)數(shù)組:delete [] p;
  • 標(biāo)準(zhǔn)庫(kù)提供了一個(gè)可以管理new分配的數(shù)組的unique_ptr版本:unique_ptrp(new int[]10);,可以使用下標(biāo)運(yùn)算符來訪問數(shù)組中的元素。與unique_ptr不同,shared_ptr不直接支持管理動(dòng)態(tài)數(shù)組,如果要使用shared_ptr管理,必須提供自定義的刪除器shared_ptrp(new int[10],[](int *p){delete[] p});,并且不能使用下標(biāo)運(yùn)算符,只能用gert()獲取內(nèi)置指針后再訪問數(shù)組元素
  • new將內(nèi)存分配和對(duì)象構(gòu)造結(jié)合在了一起,delete將對(duì)象析構(gòu)和內(nèi)存釋放結(jié)合在了一起,這樣在分配少量對(duì)象時(shí)方便使用,但是當(dāng)要分配大量?jī)?nèi)存時(shí),希望將內(nèi)存分配和對(duì)象構(gòu)造分離。標(biāo)準(zhǔn)庫(kù)allocator定義在頭文件中,提供了一種類型感知的內(nèi)存分配方法,分配的內(nèi)存是未構(gòu)造的
  • allocator類算法:①allocatora:定義一個(gè)可以為類型T分配內(nèi)存的allocator對(duì)象;②a.allocator(n):分配一段可以保存n個(gè)類型為T的對(duì)象的未構(gòu)造的內(nèi)存;③a.deallocator(p,n):釋放從T*指針p開始的n個(gè)T類型對(duì)象的內(nèi)存,p必須分配過n個(gè)T類型對(duì)象,且已被創(chuàng)建的對(duì)象必須調(diào)用過destroy;④a.construct(p,args):在p指向的未構(gòu)造內(nèi)存中通過args構(gòu)造一個(gè)對(duì)象;⑤a.destory(p):對(duì)p指向的對(duì)象執(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海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

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

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

廣告

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

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