C++primer 第 3 章 字符串、向量和数组 3 . 5 数组
生活随笔
收集整理的這篇文章主要介紹了
C++primer 第 3 章 字符串、向量和数组 3 . 5 数组
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
3.5數(shù)組
- 數(shù)組是一種類似于標(biāo)準(zhǔn)庫類型vector(參見3.3節(jié),第86頁)的數(shù)據(jù)結(jié)構(gòu),但是在性能和靈活性的權(quán)衡上又與vector有所不同。與vector相似的地方是,數(shù)組也是存放類型相同的對象的容器,這些對象本身沒有名字,需要通過其所在位置訪問。與vector不同的地方是,數(shù)組的大小確定不變,不能隨意向數(shù)組中增加元素。因為數(shù)組的大小固定,
- 因此對某些特殊的應(yīng)用來說程序的運行時性能較好,但是相應(yīng)地也損失了一些靈活性。
- 如果不清楚元素的確切個藪,請使用vector
3.5.1定義和初始化內(nèi)置數(shù)組
- 數(shù)組是一種復(fù)合類型(參見2.3節(jié),第45頁)。數(shù)組的聲明形如a[d],其中a是數(shù)組的名字,d是數(shù)組的維度。維度說明了數(shù)組中元素的個數(shù),因此必須大于0。數(shù)組中元素的個數(shù)也屬于數(shù)組類型的一部分,編譯的時候維度應(yīng)該是已知的。也就是說,維度必須是一個常量表達式(參見2.4.4節(jié),第58頁):
- 和內(nèi)置類型的變量一樣,如果在函數(shù)內(nèi)部定義了某種內(nèi)置類型的數(shù)組,那么默認初始化會令數(shù)組含有未定義的值,
- 定義數(shù)組的時候必須指定數(shù)組的類型,不允許用auto。關(guān)鍵字由初始值的列表推斷類型。另外和vector一樣,數(shù)組的元素應(yīng)為對象,因此不存在引用的數(shù)組
顯式初始化數(shù)組元素
- 可以對數(shù)組的元素進行列表初始化(參見3.3.1節(jié),第88頁),此時允許忽略數(shù)組的維度。如果在聲明時沒有指明維度,編譯器會根據(jù)初始值的數(shù)量計算并推測出來;相反,如果指明了維度,那么初始值的總數(shù)量不應(yīng)該超出指定的大小。如果維度比提供的初始值數(shù)量大,則用提供的初始值初始化靠前的元素,剩下的元素被初始化成默認值(參見3.3.1節(jié),第88頁):
字符數(shù)組的特殊性
- 字符數(shù)組有一種額外的初始化形式,我們可以用字符串字面值(參見2.1.3節(jié),第36頁)對此類數(shù)組初始化。當(dāng)使用這種方式時,一定要注意字符串字面值的結(jié)尾處還有一個空字符,這個空字符也會像字符串的其他字符一樣被拷貝到字符數(shù)組中去:
- al的維度是3,a2和a3的維度都是4,a4的定義是錯誤的。盡管字符串字面值"Daniel1看起來只有6個字符,但是數(shù)組的大小必須至少是7,其中6個位置存放字面值的內(nèi)容,另外1個存放結(jié)尾處的空字符。
理解復(fù)雜的數(shù)組聲明
- 和vector-樣,數(shù)組能存放大多數(shù)類型的對象。例如,可以定義一個存放指針的數(shù)組。又因為數(shù)組本身就是對象,所以允許定義數(shù)組的指針及數(shù)組的引用。在這幾種情況中,定義存放指針的數(shù)組比較簡單和直接,但是定義數(shù)組的指針或數(shù)組的引用就稍微復(fù)雜一點了:
- 默認情況下,類型修飾符從右向左依次綁定。對于Ptrs來說,從右向左(參見2.3.3節(jié),第52頁)理解其含義比較簡單:首先知道我們定義的是一個大小為10的數(shù)組,它的名字是ptrs,然后知道數(shù)組中存放的是指向int的指針。但是對于Parray來說,從右向左理解就不太合理了。因為數(shù)組的維度是緊跟著被聲明的名字的,所以就數(shù)組而言,由內(nèi)向外閱讀要比從右向左好多了。由內(nèi)向外的順序可幫助我們更好地理解Parray的含義:首先是圓括號括起來的部分,*Parray意味著Parray是個指針,接下來觀察右邊,可知道Parray是個指向大小為10的數(shù)組的指針,最后觀察左邊,知道數(shù)組中的元素是int。這樣最終的含義就明白無誤了,Parray是一個指針,它指向一個int數(shù)組,數(shù)組中包含10個元素。同S,(&arrRef)表示arrRef是一個引用,它引用的對象是一個大小為10的數(shù)組,數(shù)組中元素的類型是int。當(dāng)然,對修飾符的數(shù)量并沒有特殊限制:
- in t * (&arry) [10] = p tr s ; / / a r r y 是數(shù)組的引用,該 數(shù) 組含有 1 0 個指針
- 按照由內(nèi)向外的順序閱讀上述語句,首先知道arry是一個引用,然后觀察右邊知道,arry引用的對象是一個大小為10的數(shù)組,最后觀察左邊知道,數(shù)組的元素類型是指向int的指針。這樣,arry就是一個含有10個int型指針的數(shù)組的引用
- 要想理解數(shù)組聲明的含義,最好的辦法是從數(shù)組的名字開始按照由內(nèi)向外的順序閱讀"
3 .5 .2 訪問數(shù)組元素
- 與標(biāo)準(zhǔn)庫類型vector和string一樣,數(shù)組的元素也能使用范圍for語句或下標(biāo)運算符來訪問。數(shù)組的索引從0開始,以一個包含10個元素的數(shù)組為例,它的索引從0到9,而非從1到10。
- 在使用數(shù)組下標(biāo)的時候,通常將其定義為size_t類型。size_t是一種機器相關(guān)的無符號類型,它被設(shè)計得足夠大以便能表示內(nèi)存中任意對象的大小。在cstdef頭文件中定義了sizet類型,這個文件是C標(biāo)準(zhǔn)庫stddef.h頭文件的C++語言版本。
?
3 .5 .3 指針和數(shù)組
- 在C++語言中,指針和數(shù)組有非常緊密的聯(lián)系。就如即將介紹的,使用數(shù)組的時候編譯器一般會把它轉(zhuǎn)換成指針。
- 通常情況下,使用取地址符(參見2.3.2節(jié),第47頁)來獲取指向某個對象的指針,取地址符可以用于任何對象。數(shù)組的元素也是對象,對數(shù)組使用下標(biāo)運算符得到該數(shù)組指定位置的元素。因此像其他對象一樣,對數(shù)組的元素使用取地址符就能得到指向該元素的指針:
- string nums [] = {"one”, "two", *'threen ; // 數(shù)組的元素是 string 對象
- string *p = &nums [0] ; // p 指向 nums 的第一個元素
- 然而,數(shù)組還有一個特性:在很多用到數(shù)組名字的地方,編譯器都會自動地將其替換為一個指向數(shù)組首元素的指針:
- string *p2 = nums; // 等價于 p2 = &nums [0]
- 在大多數(shù)表達式中,使用數(shù)組類型的對象其實是使用一個指向該數(shù)組首元素的指針。
- 由上可知,在一些情況下數(shù)組的操作實際上是指針的操作,這一結(jié)論有很多隱含的意思。其中一層意思是當(dāng)使用數(shù)組作為一個auto (參見2.5.2節(jié),第 61頁)變量的初始值 時,推斷得到的類型是指針而非數(shù)組:
指針也是迭代器
- 與2.3.2節(jié)(第47頁)介紹的內(nèi)容相比,指向數(shù)組元素的指針擁有更多功能。vector和string的迭代器(參見3.4節(jié),第95頁)支持的運算,數(shù)組的指針全都支持。例如,允許使用遞增運算符將指向數(shù)組元素的指針向前移動到下一個位置上:
- int arr[] = 10,1,2,3,4,5,6,7,8,9};
- int *p = arr; // p 指 向 arr的第一個元素
- ++p; // p 指向 arr [1]
- 就像使用迭代器遍歷vector對象中的元素一樣,使用指針也能遍歷數(shù)組中的元素。當(dāng)然,這樣做的前提是先得獲取到指向數(shù)組第一個元素的指針和指向數(shù)組尾元素的下一位置的指針。之前已經(jīng)介紹過,通過數(shù)組名字或者數(shù)組中首元素的地址都能得到指向首元素的指針;不過獲取尾后指針就要用到數(shù)組的另外一個特殊性質(zhì)了。我們可以設(shè)法獲取數(shù)組尾元素之后的那個并不存在的元素的地址:
- in t *e = &arr [10] ; / / 指向a r r 尾元素的下一位置的指針
- 這里顯然使用下標(biāo)運算符索引了一個不存在的元素,arr有 10個元素,尾元素所在位置的索引是9 , 接下來那個不存在的元素唯一的用處就是提供其地址用于初始化e , 就像尾后迭代器(參見3.4.1節(jié),第 95頁)一樣,尾后指針也不指向具體的元素。因此,不能對尾后指針執(zhí)行解引用或遞增的操作。利用上面得到的指針能重寫之前的循環(huán),令其輸出arr的全部元素:
- for ( int *b = arr ; b != e ; ++b)
cout ? *b ? endl; // 輸出 arr 的元素
標(biāo)準(zhǔn)庫函數(shù)begin和end
- 盡管能計算得到尾后指針,但這種用法極易出錯。為了讓指針的使用更簡單、更安全,C++11新標(biāo)準(zhǔn)引入了兩個名為begin和end的函數(shù)。這兩個函數(shù)與容器中的兩個同名成員(參見3.4.1節(jié),第95頁)功能類似,不過數(shù)組畢竟不是類類型,因此這兩個函數(shù)不是成員函數(shù)。正確的使用形式是將數(shù)組作為它們的參數(shù):
- begin函數(shù)返回指向ia首元素的指針,end函數(shù)返回指向ia尾元素下一位置的指針,這兩個函數(shù)定義在iterator頭文件中。使用begin和end可以很容易地寫出一個循環(huán)并處理數(shù)組中的元素。例如,假設(shè)arr是一個整型數(shù)組,下面的程序負責(zé)找到arr中的第一個負數(shù)
- 首先定義了兩個名為pbeg和pend的整型指針,其中pbeg指向arr的第一個元素,pend指向arr尾元素的下一位置。while語句的條件部分通過比較pbeg和pend來確保可以安全地對pbeg解引用,如果pbeg確實指向了一個元素,將其解引用并檢查元素值是否為負值。如果是,條件失效、退出循環(huán);如果不是,將指針向前移動一位繼續(xù)考查下一個元素。
- 一個指針如果指向了某種內(nèi)置類型數(shù)組的尾元素的“下一位置”,則其具備與ivector的end函數(shù)返回的與迭代器類似的功能。特別要注意,尾后指針不能執(zhí)行解引用和遞增操作,"
指針運算
- 指向數(shù)組元素的指針可以執(zhí)行表3.6 (第96頁 )和 表 3.7 (第 99頁)列出的所有迭代器運算。這些運算,包括解引用、遞增、比較、與整數(shù)相加、兩個指針相減等,用在指針和用在迭代器上意義完全一致。給(從)一個指針加上(減去)某整數(shù)值,結(jié)果仍是指針。新指針指向的元素與原來的指針相比前進了(后退了)該整數(shù)值個位置
- ip加上4所得的結(jié)果仍是一個指針,該指針?biāo)傅脑嘏cip原來所指的元素相比前進了 4個位置。給指針加上一個整數(shù),得到的新指針仍需指向同一數(shù)組的其他元素,或者指向同一數(shù)組的尾元素的下一位置:
- / / 正確:arr轉(zhuǎn)換成指向它首元素的指針;p 指向arr尾元素的下一位置
- int *p = arr + sz; / / 使用警告:不要解引用!
- int *p2 = arr + 10; / / 錯誤:arr只 有 5 個元素,p2的值未定義
- 當(dāng)給arr加上sz時,編譯器自動地將arr轉(zhuǎn)換成指向數(shù)組arr中首元素的指針。執(zhí)行加法后,指針從首元素開始向前移動了sz(這里是5)個位置,指向新位置的元素。也就是說,它指向了數(shù)組arr尾元素的下一位置。如果計算所得的指針超出了上述范圍就將產(chǎn)生錯誤,而且這種錯誤編譯器一般發(fā)現(xiàn)不了。
- 和迭代器一樣,兩個指針相減的結(jié)果是它們之間的距離。參與運算的兩個指針必須指向同一個數(shù)組當(dāng)中的元素:
- auto n=end(arr)-begin(arr);//n的值是5,也就是arr中元素的數(shù)量
- 兩個指針相減的結(jié)果的類型是一種名為ptrdiff_t的標(biāo)準(zhǔn)庫類型,和size_t一樣,ptrdiff_t也是一種定義在cstddef頭文件中的機器相關(guān)的類型。因為差值可能為負值,所以ptrdiff_t是一種帶符號類型。只要兩個指針指向同一個數(shù)組的元素,或者指向該數(shù)組的尾元素的下一位置,就能利用關(guān)系運算符對其進行比較。例如,可以按照如下的方式遍歷數(shù)組中的元素:
- 盡管作用可能不是特別明顯,但必須說明的是,上述指針運算同樣適用于空指針(參見2.3.2節(jié),第48頁)和所指對象并非數(shù)組的指針。在后一種情況下,兩個指針必須指向同一個對象或該對象的下一位置。如果p是空指針,允許給p加上或減去一個值為0的整型常量表達式(參見2.4.4節(jié),第58頁)。兩個空指針也允許彼此相減,結(jié)果當(dāng)然是0。
解引用和指針運算的交互
- 指針加上一個整數(shù)所得的結(jié)果還是一個指針。假設(shè)結(jié)果指針指向了一個元素,則允許解引用該結(jié)果指針:
- int ia[] = (0,2,4,6,8}; / / 含 有 5個整數(shù)的數(shù)組
- int last = * (ia + 4 ); / / 正確:把 last初始化成8,也 就 是 ia [4]的值
- 表達式*(ia+4)計算ia前進4個元素后的新地址,解引用該結(jié)果指針的效果等價于表達式 ia[4]
- 回憶一下在3.4.1節(jié) (第98頁)中介紹過如果表達式含有解引用運算符和點運算符,最好在必要的地方加上圓括號。類似的,此例中指針加法的圓括號也不可缺少。如果寫成下面的形式:last = *ia + 4; // 正確: last =4 等價于 ia [0] + 4含義就與之前完全不同了,此時先解引用ia,然后給解引用的結(jié)果再加上4。4.1.2節(jié) (第 121頁)將對這一問題做進一步分析。
- 雖然標(biāo)準(zhǔn)庫類型string和vector也能執(zhí)行下標(biāo)運算,但是數(shù)組與它們相比還是有所不同。標(biāo)準(zhǔn)庫類型限定使用的下標(biāo)必須是無符號類型,而內(nèi)置的下標(biāo)運算無此要求,上面的最后一個例子很好地說明了這一點。內(nèi)置的下標(biāo)運算符可以處理負值,當(dāng)然,結(jié)果地址必須指向原來的指針?biāo)竿粩?shù)組中的元素(或是同一數(shù)組尾元素的下一位置)。
- 內(nèi)置的下標(biāo)運算符所用的索引值不是無符號類型,這一點與vector和string 不一樣。
3.5.4 C 風(fēng)格字符串
- 字符串字面值是一種通用結(jié)構(gòu)的實例,這種結(jié)構(gòu)即是C++由C繼承而來的C風(fēng)格字符串(C-stylecharacterstring)oC風(fēng)格字符串不是一種類型,而是為了表達和使用字符串而形成的一種約定俗成的寫法。按此習(xí)慣書寫的字符串存放在字符數(shù)組中并以空字符結(jié)束。以空字符結(jié)束的意思是在字符串最后一個字符后面跟著一個空字符。一般利用指針來操作這些字符串。
C標(biāo)準(zhǔn)庫String函數(shù)
- 表 3.8列舉了 C 語言標(biāo)準(zhǔn)庫提供的一組函數(shù),這些函數(shù)可用于操作C 風(fēng)格字符串,它們定義在cstring頭文件中,cstring是 C 語言頭文件string.h 的 C++版本
- 表 3.8所列的函數(shù)不負責(zé)驗證其字符串參數(shù):
- 傳入此類函數(shù)的指針必須指向以空字符作為結(jié)束的數(shù)組:不遇到 '\0' 不結(jié)束
比較字符串
- 比較兩個C風(fēng)格字符串的方法和之前學(xué)習(xí)過的比較標(biāo)準(zhǔn)庫string對象的方法大相徑庭。比較標(biāo)準(zhǔn)庫string對象的時候,用的是普通的關(guān)系運算符和相等性運算符:
- 謹記之前介紹過的,當(dāng)使用數(shù)組的時候其實真正用的是指向數(shù)組首元素的指針(參見3.5.3節(jié),第 105頁)。因此,上面的if 條件實際上比較的是兩個const char*的值。這兩個指針指向的并非同一對象,所以將得到未定義的結(jié)果。
- 比較兩個C風(fēng)格字符串需要調(diào)用strcmp函數(shù),此時比較的就不再是指針了。如果兩個字符串相等,strcmp返回0;如果前面的字符串較大,返回正值;如果后面的字符串較大,返回負值:
- if (strcmp (cal, ca2) < 0) // 和兩個 string 對象的比較 si < s2 效果一樣
- -個潛在的問題是,我們在估算largeStr所需的空間時不容易估準(zhǔn),而且largeStr所存的內(nèi)容一旦改變,就必須重新檢查其空間是否足夠。不幸的是,這樣的代碼到處都是,程序員根本沒法照顧周全。這類代碼充滿了風(fēng)險而且經(jīng)常導(dǎo)致嚴重的安全泄漏。
- 對大多數(shù)應(yīng)用來說,使用標(biāo)準(zhǔn)庫string要比使用C 風(fēng)格字符串更安全、更高效
3.5.5與舊代碼的接口
- 很多C++程序在標(biāo)準(zhǔn)庫出現(xiàn)之前就已經(jīng)寫成了,它們肯定沒用到string和vector類型。而且,有一些C程序?qū)嶋H上是與C語言或其他語言的接口程序,當(dāng)然也無法使用C++標(biāo)準(zhǔn)庫。因此,現(xiàn)代的C++程序不得不與那些充滿了數(shù)組和/或C風(fēng)格字符串的代碼銜接,為了使這一工作簡單易行,C++專門提供了一組功能。
混用string對象和C風(fēng)格字符串
- 3.2.1節(jié)(第76頁)介紹過允許使用字符串字面值來初始化string對象
- string s ("Hello World") ; // s 的內(nèi)容是 Hello World
- 更一般的情況是,任何出現(xiàn)字符串字面值的地方都可以用以空字符結(jié)束的字符數(shù)組來替代:
- 允許使用以空字符結(jié)束的字符數(shù)組來初始化string對象或為string對象賦值。
- 在string對象的加法運算中允許使用以空字符結(jié)束的字符數(shù)組作為其中一個運算對象(不能兩個運算對象都是);在string對象的復(fù)合賦值運算中允許使用以空字符結(jié)束的字符數(shù)組作為右側(cè)的運算對象。
- 上述性質(zhì)反過來就不成立了:如果程序的某處需要一個C風(fēng)格字符串,無法直接用string對象來代替它。例如,不能用string對象直接初始化指向字符的指針。為了完成該功能,string專門提供了一個名為c_str的成員函數(shù):
- char* str=s;//錯誤:不能用string對象初始化char*
- const char* str=s.cstr();//正確?
- 顧名思義,c_str函數(shù)的返回值是一個C風(fēng)格的字符串。也就是說,函數(shù)的返回結(jié)果是一個指針,該指針指向一個以空字符結(jié)束的字符數(shù)組,而這個數(shù)組所存的數(shù)據(jù)恰好與那個string對象的一樣。結(jié)果指針的類型是const char*,從而確保我們不會改變字符數(shù)組的內(nèi)容。
- 我們無法保證c_str函數(shù)返回的數(shù)組一直有效,事實上,如果后續(xù)的操作改變了 s 的值就可能讓之前返向的數(shù)組失去效用。
- 如果執(zhí)行完c_str ()函數(shù)后程序想一直都能使用其返回的數(shù)組,最好將該數(shù) 組重新拷貝一份
使用數(shù)組初始化vector對象
- 3.5.1節(jié)(第102頁)介紹過不允許使用一個數(shù)組為另一個內(nèi)置類型的數(shù)組賦初值,也不允許使用vector對象初始化數(shù)組。相反的,允許使用數(shù)組來初始化vector對象。要實現(xiàn)這一目的,只需指明要拷貝區(qū)域的首元素地址和尾后地址就可以了:
- 在上述代碼中,用于創(chuàng)建ivec的兩個指針實際上指明了用來初始化的值在數(shù)組int_arr中的位置,其中第二個指針應(yīng)指向待拷貝區(qū)域尾元素的下一位置。此例中,使用標(biāo)準(zhǔn)庫函數(shù)begin和end(參見3.5.3節(jié),第106頁)來分別計算int_arr的首指針和尾后指針。在最終的結(jié)果中,ivec將包含6個元素,它們的次序和值與數(shù)組int arr完全相同
3.6多維數(shù)組
- 嚴格來說,C++語言中沒有多維數(shù)組,通常所說的多維數(shù)組其實是數(shù)組的數(shù)組。謹記這一點,對今后理解和使用多維數(shù)組大有益處。當(dāng)一個數(shù)組的元素仍然是數(shù)組時,通常使用兩個維度來定義它:一個維度表示數(shù)組本身大小,另外-個維度表示其元素(也是數(shù)組)大小:
- 如3.5.1節(jié)(第103頁)所介紹的,按照由內(nèi)而外的順序閱讀此類定義有助于更好地理解其真實含義。在第一條語句中,我們定義的名字是ia,顯然ia是一個含有3個元素的數(shù)組。接著觀察右邊發(fā)現(xiàn),ia的元素也有自己的維度,所以ia的元素本身又都是含有4個元素的數(shù)組。再觀察左邊知道,真正存儲的元素是整數(shù)。因此最后可以明確第一條語句的含義:它定義了一個大小為3的數(shù)組,該數(shù)組的每個元素都是含有4個整數(shù)的數(shù)組。
- 使用同樣的方式理解arr的定義。首先arr是一個大小為10的數(shù)組,它的每個元素都是大小為20的數(shù)組,這些數(shù)組的元素又都是含有30個整數(shù)的數(shù)組。實際上,定義數(shù)組時對下標(biāo)運算符的數(shù)量并沒有限制,因此只要愿意就可以定義這樣一個數(shù)組:它的元素還是數(shù)組,下一級數(shù)組的元素還是數(shù)組,再下一級數(shù)組的元素還是數(shù)組,以此類推。
- 對于二維數(shù)組來說,常把第一個維度稱作行,第二個維度稱作列。
多維數(shù)組的下標(biāo)引用
- 可以使用下標(biāo)運算符來訪問多維數(shù)組的元素,此時數(shù)組的每個維度對應(yīng)一個下標(biāo)運算符。如果表達式含有的下標(biāo)運算符數(shù)量和數(shù)組的維度一樣多,該表達式的結(jié)果將是給定類型的元素;反之,如果表達式含有的下標(biāo)運算符數(shù)量比數(shù)組的維度小,則表達式的結(jié)果將是給定索引處的一個內(nèi)層數(shù)組:
- 在第一個例子中,對于用到的兩個數(shù)組來說,表達式提供的下標(biāo)運算符數(shù)量都和它們各自的維度相同。在等號左側(cè),ia[2]得到數(shù)組ia的最后一行,此時返回的是表示ia最后一行的那個一維數(shù)組而非任何實際元素;對這個一維數(shù)組再取下標(biāo),得到編號為[3]的元素,也就是這一行的最后一個元素。類似的,等號右側(cè)的運算對象包含3個維度。首先通過索引0得到最外層的數(shù)組,它是一個大小為20的(多維)數(shù)組;接著獲取這20個元素數(shù)組的第一個元素,得到一個大小為30的一維數(shù)組;最后再取出其中的第一個元素。
- 在第二個例子中,把row定義成一個含有4個整數(shù)的數(shù)組的引用,然后將其綁定到ia的第2行。
- 再舉一個例子,程序中經(jīng)常會用到兩層嵌套的for循環(huán)來處理多維數(shù)組的元素:
- constexpr size_t rowCnt = 3, colCnt = 4;
- 外層的for循環(huán)遍歷ia的所有元素,注意這里的元素是一維數(shù)組:內(nèi)層的for循環(huán)則遍歷那些一維數(shù)組的整數(shù)元素。此例中,我們將元素的值設(shè)為該元素在整個數(shù)組中的序號。
指針和多維數(shù)組
- 當(dāng)程序使用多維數(shù)組的名字時,也會自動將其轉(zhuǎn)換成指向數(shù)組首元素的指針。
- 定義指向多維數(shù)蛆的指針時,千萬別忘了這個多維數(shù)組實際上是數(shù)組的數(shù)組
- 因為多維數(shù)組實際上是數(shù)組的數(shù)組,所以由多維數(shù)組名轉(zhuǎn)換得來的指針實際上是指向第一個內(nèi)層數(shù)組的指針:
- 根據(jù)3.5.1節(jié) (第 103頁)提出的策略,我們首先明確(*p)意味著p 是一個指針。接著觀 察右邊發(fā)現(xiàn),指針P 所指的是一個維度為4 的數(shù)組;再觀察左邊知道,數(shù)組中的元素是整數(shù)。因此,p 就是指向含有4個整數(shù)的數(shù)組的指針。
- 外層的for循環(huán)首先聲明一個指針p并令其指向ia的第一個內(nèi)層數(shù)組,然后依次迭代直到ia的全部3行都處理完為止。其中遞增運算++p負責(zé)將指針p移動到ia的下一行。內(nèi)層的for循環(huán)負責(zé)輸出內(nèi)層數(shù)組所包含的值。它首先令指針q指向p當(dāng)前所在行的第一個元素。*p是一個含有4個整數(shù)的數(shù)組,像往常一樣,數(shù)組名被自動地轉(zhuǎn)換成指向該數(shù)組首元素的指針。內(nèi)層for循環(huán)不斷迭代直到我們處理完了當(dāng)前內(nèi)層數(shù)組的所有元素為止。為了獲取內(nèi)層for循環(huán)的終止條件,再一次解引用p得到指向內(nèi)層數(shù)組首元素的指針,給它加上4就得到了終止條件。
- 當(dāng)然,使用標(biāo)準(zhǔn)庫函數(shù)begin和end(參見3.5.3節(jié),第106頁)也能實現(xiàn)同樣的功能,而且看起來更簡潔一些:
- 在這一版本的程序中,循環(huán)終止條件由end函數(shù)負責(zé)判斷。雖然我們也能推斷出p的類型是指向含有4個整數(shù)的數(shù)組的指針,q的類型是指向整數(shù)的指針,但是使用auto。關(guān)鍵字我們就不必再煩心這些類型到底是什么了
小結(jié)
- string和vector是兩種最重要的標(biāo)準(zhǔn)庫類型。string對象是一個可變長的字符序列,vector對象是一組同類型對象的容器。迭代器允許對容器中的對象進行間接訪問,對于string對象和vector對象來說,可以通過迭代器訪問元素或者在元素間移動。
- 數(shù)組和指向數(shù)組元素的指針在一個較低的層次上實現(xiàn)了與標(biāo)準(zhǔn)庫類型string和vector類似的功能。一般來說,應(yīng)該優(yōu)先選用標(biāo)準(zhǔn)庫提供的類型,之后再考慮C++語言內(nèi)置的低層的替代品數(shù)組或指針。
術(shù)語表
- begin是string和vector的成員,返回指向第一個元素的迭代器。也是一個標(biāo)準(zhǔn)庫函數(shù),輸入一個數(shù)組,返回指向該數(shù)組首元素的指針。
- 緩沖區(qū)溢出(bufferoverflow)一種嚴重的程序故障,主要的原因是試圖通過一個越界的索引訪問容器內(nèi)容,容器類型包括string、vector和數(shù)組等。
- C風(fēng)格字符串(C-stylestring)以空字符結(jié)束的字符數(shù)組。字符串字面值是C風(fēng)格字符串,C風(fēng)格字符串容易出錯。
- 類模板用于創(chuàng)建具體類類型的模板。要想使用類模板,必須提供關(guān)于類型的輔助信息。例如,要定義一個vector對象需要指定元素的類型:vector<int>包含int類型的元素。
- 編譯器擴展(compilerextension)某個特定的編譯器為C++語言額外增加的特性。基于編譯器擴展編寫的程序不易移植到其他編譯器上。
- 容器(container)是一種類型,其對象容納了一組給定類型的對象。vector是一種容器類型。
- 拷貝初始化(copyinitialization)使用賦值號(=)的初始化形式。新創(chuàng)建的對象是初始值的一個副本。
- difference_type由string和vector定義的一種帶符號整數(shù)類型,表示兩個迭代器之間的距離。
- 直接初始化(directinitialization)不使用賦值號(=)的初始化形式。
- empty是string和vector的成員,返回一個布爾值。當(dāng)對象的大小為0時返回真,否則返回假.
- end是string和vector的成員,返回一個尾后迭代器。也是一個標(biāo)準(zhǔn)庫函數(shù),輸入一個數(shù)組,返回指向該數(shù)組尾元素的下-位置的指針。
- getline在string頭文件中定義的一個函數(shù),以一個istream對象利--個string對象為輸入?yún)?shù)。該函數(shù)首先讀取輸入流的內(nèi)容直到遇到換行符停止,然后將讀入的數(shù)據(jù)存入string對象,最后返回istream對象。其中換行符讀入但是不保留。
- 索引(index)是下標(biāo)運算符使用的值。表示要在string對象、vector對象或者數(shù)組中訪問的一個位置。
- 實例化(instantiation)編譯器生成一個指定的模板類或函數(shù)的過程。
- 迭代器(iterator)是一種類型,用于訪問容器中的元素或者在元素之間移動。
- 迭代器運算(iteratorarithmetic)是string或vector的迭代器的運算:迭代器與整數(shù)相加或相減得到一個新的迭代器,與原來的迭代器相比,新迭代器向前或向后移動了若干個位置。兩個迭代器相減得到它們之間的距離,此時它們必須指向同一個容器的元素或該容器尾元素的下一位置。
- 以空字符結(jié)束的字符串(null-terminatedstring)是一個字符串,它的最后一個字符后而還跟著一個空字符("\0")。
- 尾后迭代器(off-the-enditerator)end函數(shù)返I可的迭代器,指向一個并不存在的元素,該元素位于容器尾元素的下一位置。
- 指針運算(pointerarithmetic)是指針類型支持的算術(shù)運算。指向數(shù)組的指針?biāo)С值倪\算種類與迭代器近算一樣。
- prtdiff_t是cstddef頭文件中定義的一種與機器實現(xiàn)有關(guān)的帶符號整數(shù)類型,它的空間足夠大,能夠表示數(shù)組中任意兩個指針之間的距離。
- pushback是vector的成員,向vector對象的木尾添加元素。
- 范圍for語句(rangefor)-種控制語句,可以在值的一個特定集合內(nèi)迭代。
- size是string和vector的成員,分別返回字符的數(shù)量或元素的數(shù)量。返回值的類型是size_type。size_t是cstddef頭文件中定義的一種與機器實現(xiàn)有關(guān)的無符號整數(shù)類型,它的空間足夠大,能夠表示任意數(shù)組的大小。
- size_type是string和vector定義的類型的名字,能存放下任意string對象或vector對象的大小。在標(biāo)準(zhǔn)中,size_type被定義為無符號類型。string是一種標(biāo)準(zhǔn)庫類型,表示字符的序列。
- using聲明(usingdeclaration)令命名空間中的某個名字可被程序直接使用。using命名空間::名字;L述語句的作用是令程序可以直接使用名字,而無須寫它的前綴部分命名空間
- 值初始化(valueinitialization)是一種初始化過程。內(nèi)置類型初始化為0,類類型由類的默認構(gòu)造函數(shù)初始化。只有當(dāng)類包含默認構(gòu)造函數(shù)時,該類的對象才會被值初始化。對于容器的初始化來說,如果只說明了容器的大小而沒有指定初始值的話,就會執(zhí)行值初始化。此時編譯器會生成一個值,而容器的元素被初始化為該值。
- vector是-種標(biāo)準(zhǔn)庫類型,容納某指定類型的一組元素。
- ++運算符(++operator)是迭代器和指針定義的遞增運算符。執(zhí)行“加1”操作使得迭代器指向下一個元素
- []運算符([]operator)下標(biāo)運算符Oobj[j]得到容器對象。bj中位置j的那個元素。索引從0開始,第一個元素的索引是0,
- 尾元素的索引是。bj.size()-1.下'標(biāo)運算符的返回值是一個對象。如果p是指針、n是整數(shù),則p[n]與*(p+n)等價。->運算符(->operator)箭頭運算符,該運算符綜合了解引用操作和點操作.a->b等價于(*a).b。
- <<運算符(《operator)標(biāo)準(zhǔn)庫類型string定義的輸出運算符,負責(zé)輸出string對象中的字符。
- >>運算符(>>operator)標(biāo)準(zhǔn)庫類型string定義的輸入運算符,負責(zé)讀入一組字符,遇到空白停止,讀入的內(nèi)容賦給運算符右側(cè)的運算對象,該運算對象應(yīng)該是一個string對象。
- !運算符^operator)邏輯非運算符,將它的運算對象的布爾值取反。如果運算對象是假,則結(jié)果為真,如果運算對象是真:,則結(jié)果為假。
- &&運算符(&&operator)邏輯與運算符,如果兩個運算對象都是真,結(jié)果為真。只有當(dāng)左側(cè)運算對象為真時才會檢查右側(cè)運算對象。
- II運算符(||operator)邏輯或運算符,任何一個運算對象是真,結(jié)果就為真。只有里左側(cè)運算對象為假時才會檢查右側(cè)運算對象。
總結(jié)
以上是生活随笔為你收集整理的C++primer 第 3 章 字符串、向量和数组 3 . 5 数组的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有“钱”途才是真王道 细数十种职业的灰色
- 下一篇: 《原神》3.1版本PV:沙漠开放 坎蒂丝