C++中的復(fù)合類(lèi)型,包括以下幾個(gè)內(nèi)容:
1、創(chuàng)建和使用數(shù)組。
2、創(chuàng)建和使用C-風(fēng)格字符串。
3、創(chuàng)建和使用string類(lèi)字符串。
4、使用方法getline()和get()讀取字符串。
5、混合輸入字符串和數(shù)字。
6、創(chuàng)建和使用結(jié)構(gòu)體。
7、創(chuàng)建和使用共用體。
8、創(chuàng)建和使用枚舉。
9、創(chuàng)建和使用指針。
10、使用new和delete管理動(dòng)態(tài)內(nèi)存。
11、創(chuàng)建動(dòng)態(tài)數(shù)組。
12、創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)。
13、自動(dòng)存儲(chǔ)、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)。
14、Vector和array類(lèi)簡(jiǎn)介。
一、數(shù)組
使用數(shù)組,首先要聲明數(shù)組:typeName arrayName[arraysize];訪(fǎng)問(wèn)數(shù)組元素可以使用帶索引的方括號(hào)表示法來(lái)指定數(shù)組元素。
有效下標(biāo)的重要性:
編譯器不會(huì)檢查使用的下標(biāo)是否有效,但是程序運(yùn)行后,這種賦值可能引發(fā)問(wèn)題,它可能破壞數(shù)據(jù)或代碼,也可能導(dǎo)致程序異常終止。
1.1數(shù)組的初始化規(guī)則
只有在定義數(shù)組時(shí)才能初始化,此后就不能使用了,也不能將一個(gè)數(shù)組賦給另一個(gè)數(shù)組:
Int cards[4]={3,6,8,10}; //okay
Int hand[4]; //okay
Hand[4]={5,6,7,9};//not allowed
Hand=cards;//not allowed
1.2 C++11數(shù)組初始化方法
C++11的列表初始化新增了一些功能
(1)初始化數(shù)組時(shí),可省略等號(hào)(=):
double earnings[4] {1.2e4,1.6e4,1.1e4,1.7e4};
(2)可不在大括號(hào)內(nèi)包含任何東西,這將把所有的元素都設(shè)置為零。
(3)列表初始化禁止縮窄轉(zhuǎn)換。
二、字符串
C++處理字符串的方式有兩種。第一種來(lái)自C語(yǔ)言,常稱(chēng)為C-風(fēng)格字符串,另一種是基于string類(lèi)庫(kù)的方法。
C-風(fēng)格字符串具有一種特殊的性質(zhì):以空字符結(jié)尾,空字符被寫(xiě)作\0,其ASCII碼為0,用來(lái)標(biāo)記字符串的結(jié)尾。
字符串常量可以用來(lái)初始化字符數(shù)組,但要區(qū)別于字符常量。
2.1拼接字符串常量
有時(shí)候字符串很長(zhǎng),無(wú)法放到一行中。C++允許拼接字符串字面值,即將兩個(gè)用引號(hào)括起的字符串合并為一個(gè)。事實(shí)上,任何兩個(gè)由空白(空格、制表符和換行符)分隔的字符串常量都將會(huì)自動(dòng)拼接成一個(gè)。
注意,拼接時(shí)不會(huì)在被連接的字符串之間添加空格,第二個(gè)字符串的第一個(gè)字符將緊跟在第一個(gè)字符串的最后一個(gè)字符后面。第一個(gè)字符串中的\0字符將被第二個(gè)字符串中的第一個(gè)字符取代。
2.2在數(shù)組中使用字符串
要將字符串存儲(chǔ)到數(shù)組中,最常見(jiàn)兩種方法——將數(shù)組初始化為字符串常量、將鍵盤(pán)或文件輸入讀入到數(shù)組中。
可以使用標(biāo)準(zhǔn)C語(yǔ)言庫(kù)函數(shù)strlen()來(lái)確定字符串長(zhǎng)度。標(biāo)準(zhǔn)頭文件cstring提供了該函數(shù)以及很多字符串相關(guān)的基本函數(shù)聲明。但sizeof()運(yùn)算符和Strlen()函數(shù)是有區(qū)別的,前者指出了整個(gè)數(shù)組的長(zhǎng)度,后者函數(shù)返回的是存儲(chǔ)在數(shù)組中的字符串長(zhǎng)度,而不是數(shù)組本身長(zhǎng)度,且其只計(jì)算可見(jiàn)的字符,而不把空字符計(jì)算在內(nèi)。
2.3字符串的輸入和每次讀取一行字符串的輸入
Cin使用空白來(lái)確定字符串的結(jié)束位置,這意味著cin在獲取字符數(shù)組輸入時(shí)只讀取一個(gè)單詞。讀取該單詞后,cin將該字符串放到數(shù)組中,并自動(dòng)在結(jié)尾添加空字符。
而有時(shí)需要將整條短語(yǔ)而不是一個(gè)單詞作為字符串輸入時(shí),需要采用面向行而不是面向單詞的方法??捎胕steam中類(lèi)提供的一些面向行的類(lèi)成員函數(shù):getline()和get()。這兩種函數(shù)都讀取一行輸入,直到到達(dá)換行符。然而,隨后getline()將換行符丟棄,而get()將換行符保留在輸入序列中。
(1)面向行的輸入getline()
getline()函數(shù)讀取整行,它通過(guò)回車(chē)鍵輸入的換行符來(lái)確定輸入結(jié)尾。該函數(shù)有兩個(gè)參數(shù):cin.getline(name,20);
getline()函數(shù)每次讀取一行,它通過(guò)換行符來(lái)確定行尾,但不保存換行符,相反,在存儲(chǔ)字符串時(shí),它用空字符來(lái)替換換行符。
(2)面向行的輸入get()
該函數(shù)有幾種變體。
1、類(lèi)似于getline(),它們接受的參數(shù)相同,解釋參數(shù)的方式也相同,并且都讀取到行尾。但get并不再讀取并并丟換行符,而是將其留在輸入隊(duì)列中。如果兩次調(diào)用get(),由于第一次調(diào)用后,換行符保留在輸入隊(duì)列中,因此第二次調(diào)用時(shí)看到的第一個(gè)字符便是換行符。因此get()認(rèn)為已達(dá)到行尾,而沒(méi)有發(fā)現(xiàn)任何可讀的內(nèi)容,如果不借助于幫助,get()將不能跨過(guò)該換行符。幸運(yùn)的是,get()有另一種變體,使用不帶任何參數(shù)的cin.get()調(diào)用可讀取下一個(gè)字符,即便是換行符,為讀取下一行輸入做好準(zhǔn)備。
2、將兩種類(lèi)成員函數(shù)拼接起來(lái)(合并),如下:cin.get(name,20).get()。之所以這樣做,是由于cin.get(name,20)返回一個(gè)cin對(duì)象,該對(duì)象隨后將被用來(lái)調(diào)用get()函數(shù)。
之所以使用get()函數(shù),首先,老式實(shí)現(xiàn)沒(méi)有g(shù)etline(),其次,get()使輸入更仔細(xì)。例如,用get()將一行讀入數(shù)組中,如何知道停止讀取的原因是因?yàn)橛捎谝呀?jīng)讀取了整行,而不是由于數(shù)組已經(jīng)填滿(mǎn)?查看下一個(gè)輸入字符,如果是換行符,說(shuō)明已經(jīng)讀取整行;否則,說(shuō)明該行中還有其他輸入。
2.4空行和其他問(wèn)題
當(dāng)getline()或get()讀取空行時(shí),將會(huì)發(fā)生什么?最初的做法是,下一條輸入語(yǔ)句將在前一條getline()或get()結(jié)束讀取的位置開(kāi)始讀??;但當(dāng)前的做法是,當(dāng)get()(不是getline())讀取空行后設(shè)置失效位(failbit)。這意味著接下來(lái)的輸入將被阻斷,但可以用下面的命令來(lái)恢復(fù)輸入:cin.clear();
另一個(gè)潛在問(wèn)題是,輸入字符串可能比分配的空間長(zhǎng)。如果輸入行包含的字符數(shù)比指定的多,則getline()和get()將余下的字符留在輸入隊(duì)列中,而getline()還會(huì)設(shè)置失效位,并關(guān)閉后面的輸入。
2.5混合輸入字符串和數(shù)字。
三、String類(lèi)簡(jiǎn)介
ISO/ANSIC++98標(biāo)準(zhǔn)通過(guò)添加string類(lèi)擴(kuò)展了C++庫(kù),因此可以string類(lèi)型的變量(使用C++的話(huà)說(shuō)對(duì)象)而不是字符數(shù)組來(lái)存儲(chǔ)字符串。String類(lèi)使用起來(lái)比數(shù)組簡(jiǎn)單,同時(shí)提供了將字符串作為一種數(shù)據(jù)類(lèi)型的表示方法。
要使用string類(lèi),必須在程序中包含頭文件string。String類(lèi)位于名稱(chēng)空間std中,因此必須提供一條using編譯指令,或者使用std::string來(lái)引用它。String類(lèi)定義隱藏了字符串的數(shù)組性質(zhì),能夠像處理變量那樣處理字符串。
String對(duì)象和字符數(shù)組之間的主要區(qū)別是,可以將string對(duì)象聲明為簡(jiǎn)單變量,而不是數(shù)組。類(lèi)設(shè)計(jì)讓程序能夠自動(dòng)處理string的大小。從理論上說(shuō),可以將char數(shù)組視為一組用于存儲(chǔ)一個(gè)字符串的char存儲(chǔ)單元,而string類(lèi)變量是一個(gè)表示字符串的實(shí)體。
3.1賦值、拼接和附加
使用string類(lèi)時(shí),某些操作比使用數(shù)組時(shí)更為簡(jiǎn)單。例如,不能將一個(gè)數(shù)組賦給另一個(gè)數(shù)組,但可以將一個(gè)string對(duì)象賦給另一個(gè)string對(duì)象。
String類(lèi)簡(jiǎn)化了字符串合并操作,可以使用運(yùn)算符+將兩個(gè)string對(duì)象合并起來(lái),還可以使用運(yùn)算符+=將字符串附加到string對(duì)象的末尾。
3.2string類(lèi)的其他操作
在C++新增string類(lèi)之前,要完成諸如給字符串賦值等工作,對(duì)于C-風(fēng)格字符串來(lái)說(shuō),使用C語(yǔ)言庫(kù)中的函數(shù)來(lái)完成這些任務(wù)。頭文件cstring提供了這些函數(shù)。
3.3string類(lèi)I/O
要用函數(shù)strlen()來(lái)計(jì)算空數(shù)組的字節(jié)數(shù)時(shí),得到的數(shù)組長(zhǎng)度可能是與定義的數(shù)組長(zhǎng)度是不同的。因?yàn)槲闯跏蓟臄?shù)組的內(nèi)容是未定義的,其次,函數(shù)strlen()從數(shù)組的第一個(gè)元素開(kāi)始計(jì)算字節(jié)數(shù),直到遇到空字符。對(duì)于未被初始化的數(shù)據(jù),第一個(gè)空字符的出現(xiàn)位置是隨機(jī)的。
而對(duì)于未初始化的string對(duì)象來(lái)說(shuō),其長(zhǎng)度是被自動(dòng)設(shè)置為0的,所以str.size()是等于0的。
還要區(qū)別cin.getline(Charr,20);和語(yǔ)句getline(cin,str);
對(duì)于前者來(lái)說(shuō),函數(shù)getline()是istream類(lèi)對(duì)象cin的成員函數(shù),第一個(gè)參數(shù)是目標(biāo)數(shù)組,第二個(gè)參數(shù)是數(shù)組長(zhǎng)度,用來(lái)避免超越數(shù)組的邊界。而對(duì)于后者來(lái)說(shuō),這里沒(méi)有使用句點(diǎn),說(shuō)明這個(gè)getline()不是類(lèi)方法。它將cin作為參數(shù),指出到哪里取查找輸入,另外也沒(méi)有指出字符串長(zhǎng)度的參數(shù),因?yàn)閟tring對(duì)象根據(jù)字符串長(zhǎng)度自動(dòng)調(diào)整自己的大小。
而這是為什么呢?
在引入string類(lèi)之前很久,C++就有istream類(lèi)。因?yàn)閕stream類(lèi)考慮到了諸如double和int等基本數(shù)據(jù)類(lèi)型,但沒(méi)有考慮到string類(lèi)型,所以istream類(lèi)中,有處理double、int和其他基本類(lèi)型的方法,而沒(méi)有處理string對(duì)象的類(lèi)方法。
四、結(jié)構(gòu)
結(jié)構(gòu)是用戶(hù)定義的類(lèi)型,而結(jié)構(gòu)的聲明定義了這種類(lèi)型的數(shù)據(jù)屬性。定義了類(lèi)型后,便可以創(chuàng)建這種類(lèi)型的變量。因此創(chuàng)建結(jié)構(gòu)包括兩步。首先,定義結(jié)構(gòu)描述——它描述并標(biāo)記了能夠存儲(chǔ)在結(jié)構(gòu)中的各種數(shù)據(jù)類(lèi)型。然后按描述創(chuàng)建結(jié)構(gòu)變量。
在C++中的創(chuàng)建結(jié)構(gòu)體變量與C語(yǔ)言不同,C++可以省略掉關(guān)鍵字struct,而不出錯(cuò)。
C++不提倡在使用外部變量,但體長(zhǎng)使用外部結(jié)構(gòu),在外部聲明符號(hào)常量通常更合理。
與C語(yǔ)言一樣,C++也允許指定占用特定位數(shù)的結(jié)構(gòu)成員,這使得創(chuàng)建于與某個(gè)硬件設(shè)備上的寄存器對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)非常方便。字段的類(lèi)型應(yīng)為整型或枚舉,接下來(lái)是冒號(hào),冒號(hào)后面是一個(gè)數(shù)字,它指定了使用的位數(shù)??梢允褂脹](méi)有名稱(chēng)的字段來(lái)提供間距。每個(gè)成員都被為位字段。如下:
Struct torgle_register
{
Unsigned int SN:4;
Unsigned int :4;
Bool goodIn:1;
Bool goodTorgle:1;
};
同時(shí)可以像通常那樣初始化這些字段,還可以使用標(biāo)準(zhǔn)的結(jié)構(gòu)表示法來(lái)訪(fǎng)問(wèn)這些字段。
五、共用體
共用體是一種數(shù)據(jù)結(jié)構(gòu),它能夠存儲(chǔ)不同的數(shù)據(jù)類(lèi)型,但只能同時(shí)存儲(chǔ)其中一種類(lèi)型。也就是說(shuō),結(jié)構(gòu)可以同時(shí)存儲(chǔ)int、long和double,共用體只能存儲(chǔ)int、long或double。共用體的句法與結(jié)構(gòu)相似,但含義不同。
Union one4all
{
Int int_val;
Long long_val;
Double double_val;
}
可以使用one4all變量來(lái)存儲(chǔ)int、long或double,條件是在不同的時(shí)間進(jìn)行。
One4all pail;
Pail.int_val=15;
Cout<<pail.int_val;
Pail.double_val=1,38;
Cout<<pail.double_val;
因?yàn)閜ail有時(shí)可以是int變量,有時(shí)又可以是double變量。成員名稱(chēng)標(biāo)識(shí)了變量的容量。由于共用體每次只能存儲(chǔ)一個(gè)值,因此它必須有足夠的空間來(lái)存儲(chǔ)最大的成員,所以共用體的長(zhǎng)度為其最大成員的長(zhǎng)度。
共用體的用途之一,當(dāng)數(shù)據(jù)項(xiàng)使用兩種或更多格式時(shí)(但不會(huì)同時(shí)使用),可以節(jié)省空間。另外,共用體常用于操作系統(tǒng)數(shù)據(jù)結(jié)構(gòu)或硬件數(shù)據(jù)結(jié)構(gòu)。
六、枚舉
C++的enum工具提供了另一種創(chuàng)建符號(hào)常量的方式,這種方式可以替代const。它還允許定義新的類(lèi)型,但必須按照嚴(yán)格的限制進(jìn)行。使用enum的句法與結(jié)構(gòu)相似。
enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
spectrum被稱(chēng)為枚舉,red、orange等作為符號(hào)常量,它們對(duì)應(yīng)整數(shù)0-7.這些常量叫做枚舉量。
枚舉變量有一些特殊的屬性,如下:
在不進(jìn)行強(qiáng)制轉(zhuǎn)換的情況下,只能將定義枚舉時(shí)使用的枚舉量賦給這種枚舉的變量。如:band=blue;但不能band=2000;因此,spectrum變量受到限制,只有8個(gè)可能的值,視圖將一個(gè)非法的值賦給它,則有些編譯器將出現(xiàn)編譯錯(cuò)誤,而另一些則發(fā)出警告。
對(duì)于枚舉,只定義了賦值運(yùn)算符,沒(méi)有定義算術(shù)運(yùn)算。
枚舉量是整型,可被提升為int類(lèi)型,但int類(lèi)型不能自動(dòng)轉(zhuǎn)換為枚舉類(lèi)型。
Band=3是錯(cuò)誤的,color=3+red;
但對(duì)于band=orange+red;又是錯(cuò)誤的,雖然orange+red可看成是1+0,但是其結(jié)果類(lèi)型是int,不能賦值給枚舉類(lèi)型。
枚舉更常被用來(lái)定義相關(guān)的符號(hào)常量,而不是新類(lèi)型。
6.1設(shè)置枚舉量的值
后面沒(méi)有被初始化的枚舉量的值將比前面的枚舉量大1。早期版本中,只能將int值賦給枚舉量,但這種限制取消了,因此可以使用long甚至long long類(lèi)型的值
6.2枚舉的取值范圍
最初,對(duì)于枚舉來(lái)說(shuō),只有聲明中的那些值是有效的。然而,C++現(xiàn)在通過(guò)強(qiáng)制轉(zhuǎn)換類(lèi)型,增加了可賦給枚舉變量的合法值。每個(gè)枚舉都有取值范圍,通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換,可將取值范圍中的任意整數(shù)賦值給枚舉變量,即使這個(gè)值不是枚舉值。
取值范圍的定義如下:
首先,要找到上限,需要知道枚舉量的最大值。找到大于這個(gè)最大值的并是最小的2的冪,將它減去1,得到的便是取值范圍的上限。要計(jì)算下限,需要知道枚舉量的最小值。如果它不小于0,則取值范圍的下限為0;否則,采用與尋找上限方式相同的方式,但加上負(fù)號(hào),如果最小的枚舉量為-6,而比它小的、最大的2的冪是-8,因此下限為-7.
選擇用多少空間來(lái)存儲(chǔ)枚舉由編譯器決定。對(duì)于取值范圍較小的枚舉,使用一個(gè)字節(jié)或更少的空間,而對(duì)于包含long類(lèi)型值得枚舉,則使用4個(gè)字節(jié)。
七、指針和自由存儲(chǔ)空間
極其重要的一點(diǎn):在C++中創(chuàng)建指針時(shí),計(jì)算機(jī)將分配用來(lái)存儲(chǔ)地址的內(nèi)存,但不會(huì)分配用來(lái)存儲(chǔ)指針的所指向的數(shù)據(jù)的內(nèi)存。為數(shù)據(jù)提供空間是一個(gè)獨(dú)立的步驟,忽略這一步無(wú)疑是自找麻煩,如下所示:
Long* fellow;
*fellow=223323;
上述代碼并沒(méi)有將地址賦給fellow,那么223323被放到哪就不知道了。由于fellow沒(méi)有被初始化,它可能有任何值。不管值是什么,程序都將它解釋為存儲(chǔ)223323的地址。如果fellow的值碰巧為1200,計(jì)算機(jī)把數(shù)據(jù)放到地址1200上,即使著恰巧是程序代碼的地址。Fellow指向的地方很可能并不是所要存儲(chǔ)223323的地方。這種錯(cuò)誤可能會(huì)導(dǎo)致一些最隱匿、最難以跟蹤的bug。
一定要在對(duì)指針應(yīng)用解除引用運(yùn)算符(*)之前,將指針初始化為一個(gè)確定的、適當(dāng)?shù)牡刂贰?/p>
7.1使用new來(lái)分配內(nèi)存
前面我們都將指針初始化為變量的地址:變量是在編譯時(shí)分配的有名稱(chēng)的內(nèi)存,而指針只是為通過(guò)名稱(chēng)直接訪(fǎng)問(wèn)的內(nèi)存提供了一個(gè)別名.指針真正的用武之地在于,在運(yùn)行階段分配未命名的內(nèi)存以存儲(chǔ)值.
用new運(yùn)算符就是在運(yùn)行階段為一個(gè)int值分配未命名的內(nèi)存,并用指針來(lái)訪(fǎng)問(wèn)這個(gè)值.程序員要告訴new,需要未哪種數(shù)據(jù)類(lèi)型分配內(nèi)存;new將找到一個(gè)長(zhǎng)度正確的內(nèi)存塊,并返回該內(nèi)存塊的地址。程序員的責(zé)任就是將該地址賦給一個(gè)指針。
如:int* pn=new int;
new int告訴程序,需要適合存儲(chǔ)int的內(nèi)存。New運(yùn)算符根據(jù)類(lèi)型來(lái)確定需要多少字節(jié)的內(nèi)存,并返回地址,賦給pn,pn被聲明為指向int的指針。
7.2用delete來(lái)釋放內(nèi)存
delete運(yùn)算符,它使得在使用完內(nèi)存后,能夠?qū)⑵錃w還給內(nèi)存池。使用delete時(shí),后面加上指向內(nèi)存塊的指針(這些內(nèi)存塊最初使用new分配的)。
如:delete pn;
這將釋放pn指向的內(nèi)存,但不會(huì)刪除指針pn本身。例如可以將pn重新指向另一個(gè)新分配的內(nèi)存塊,一定要配合使用new和delete,否則將發(fā)生內(nèi)存泄漏,也就是說(shuō),被分配的內(nèi)存將再也無(wú)法使用了,程序?qū)⒂捎诓粩鄬ふ腋鄡?nèi)存而終止。
不要嘗試釋放已經(jīng)釋放的內(nèi)存塊,C++標(biāo)準(zhǔn)指出,這樣做的結(jié)果是不確定的,這意味著什么情況都可能發(fā)生,另外,不能使用delete來(lái)釋放聲明變量所獲得的內(nèi)存。然而對(duì)空指針使用delete是安全的。
注意,使用delete的關(guān)鍵在于,將它用于new分配的內(nèi)存。這并不是意味著要使用用于new的指針,而是用于new的地址。一般來(lái)說(shuō),不要?jiǎng)?chuàng)建兩個(gè)指向同一個(gè)內(nèi)存塊的指針,因?yàn)檫@將增加錯(cuò)誤地刪除同一個(gè)內(nèi)存塊兩次地可能性。
7.3使用new來(lái)創(chuàng)建動(dòng)態(tài)數(shù)組
在編譯時(shí)給數(shù)組分配內(nèi)存被稱(chēng)為靜態(tài)聯(lián)編,意味著數(shù)組在編譯時(shí)加入到程序中。但使用new,如果在運(yùn)行階段需要數(shù)組,則創(chuàng)建它;如果不需要,則不創(chuàng)建。還可以在程序運(yùn)行時(shí)選擇數(shù)組長(zhǎng)度,這稱(chēng)為動(dòng)態(tài)聯(lián)編,意味著數(shù)組是在程序運(yùn)行時(shí)創(chuàng)建的。這種數(shù)組叫做動(dòng)態(tài)數(shù)組。使用靜態(tài)聯(lián)編,必須在編寫(xiě)程序時(shí)指定數(shù)組的長(zhǎng)度;使用動(dòng)態(tài)聯(lián)編時(shí),程序?qū)⒃谶\(yùn)行時(shí)確定數(shù)組的長(zhǎng)度。
創(chuàng)建動(dòng)態(tài)數(shù)組,需要將數(shù)組的元素類(lèi)型和元素?cái)?shù)目告訴new即可,
如 int* psome=new int[10];
new運(yùn)算符將返回第一個(gè)元素的地址。
釋放內(nèi)存為 delete [] psome;
方括號(hào)告訴程序應(yīng)釋放整個(gè)數(shù)組,而不僅僅是指針指向的元素。
實(shí)際上,程序跟蹤了分配的內(nèi)存量,以便以后使用delete []運(yùn)算符時(shí)能夠正確地釋放這些內(nèi)存。但這種信息是不公用地,例如,不能使用sizeof運(yùn)算符來(lái)確定動(dòng)態(tài)分配的數(shù)組包含的字節(jié)數(shù)。
八、指針、數(shù)組和指針運(yùn)算
將sizeof運(yùn)算符用于數(shù)組名時(shí),此時(shí)將返回整個(gè)數(shù)組的長(zhǎng)度。
8.1指針和字符串
數(shù)組和指針的特殊關(guān)系可以擴(kuò)展到C-風(fēng)格字符串,看下面代碼:
Char flower[10]=”rose”;
Cout<<flower<<”s are red/n”;
數(shù)組名是第一個(gè)元素的地址,因此cout語(yǔ)句中的flower是包含字符r的char元素的地址。Cout對(duì)象認(rèn)為char地址是字符串的地址,因此打印該地址出的字符,然后繼續(xù)打印后面的字符,知道遇到空字符為止。
8.2使用new創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)
將new用于結(jié)構(gòu)由兩步組成:創(chuàng)建結(jié)構(gòu)和訪(fǎng)問(wèn)其成員。要?jiǎng)?chuàng)建結(jié)構(gòu),需要同時(shí)使用結(jié)構(gòu)類(lèi)型和new。例如,要?jiǎng)?chuàng)建一個(gè)未命名的inflatable類(lèi)型,并將其地址賦給一個(gè)指針,可以這樣做:Inflatable* ps=new inflatable;
接下來(lái)要訪(fǎng)問(wèn)成員。創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)不能將成員運(yùn)算符句點(diǎn)用于結(jié)構(gòu)名,因?yàn)檫@結(jié)構(gòu)沒(méi)有名稱(chēng),只是知道它的地址。C++專(zhuān)門(mén)為這種情況提供了一個(gè)運(yùn)算符:箭頭成員運(yùn)算符(->),即ps->p。
另一種訪(fǎng)問(wèn)結(jié)構(gòu)成員的方法,如果ps是指向結(jié)構(gòu)的指針,則ps就是被指向的值——結(jié)構(gòu)本身。由于ps是一個(gè)結(jié)構(gòu),因此(*ps).price是該結(jié)構(gòu)的price成員。
8.3自動(dòng)存儲(chǔ)、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)
(1)自動(dòng)存儲(chǔ)
在函數(shù)內(nèi)部定義的常規(guī)變量使用自動(dòng)存儲(chǔ)空間,被稱(chēng)為自動(dòng)變量,這意味著它們所屬函數(shù)被調(diào)用時(shí)自動(dòng)產(chǎn)生,在函數(shù)結(jié)束時(shí)消亡。如果getname()函數(shù)返回temp的地址,則main()中的name指針指向的內(nèi)存將很快得到重新使用。這就是在getname()中使用new的原因之一。
實(shí)際上,自動(dòng)變量是一個(gè)局部變量。自動(dòng)變量通常存儲(chǔ)在棧中。這意味著執(zhí)行代碼時(shí),其中的變量將依次加入到棧中,而在離開(kāi)代碼塊時(shí),將按相反的順序釋放這些變量,這被稱(chēng)為后進(jìn)先出(LIFO)。因此,在程序執(zhí)行中,棧將不斷地增加和縮小。
(2)靜態(tài)存儲(chǔ)
靜態(tài)存儲(chǔ)是整個(gè)程序執(zhí)行期間都存在地存儲(chǔ)方式。使變量稱(chēng)為靜態(tài)的方式有兩種:一種使在函數(shù)外面定義它;另一種是在聲明變量時(shí)使用關(guān)鍵字static。
Static double fee=56.50;
(3)動(dòng)態(tài)存儲(chǔ)
New和delete運(yùn)算符提供了一種比自動(dòng)變量和靜態(tài)變量更靈活的方法。它們管理一個(gè)內(nèi)存池,這在C++中被稱(chēng)為自由存儲(chǔ)空間或堆。該內(nèi)存池同用于靜態(tài)變量和自動(dòng)變量的內(nèi)存是分開(kāi)的。New和delete讓您能夠在一個(gè)函數(shù)中分配內(nèi)存,而在另一個(gè)函數(shù)中釋放它。因此,數(shù)據(jù)的生命周期不完全受到程序或函數(shù)的生存時(shí)間控制。與使用常規(guī)變量相比,使用new和delete讓程序員對(duì)程序如何使用內(nèi)存有更大的控制權(quán)。然而內(nèi)存管理更為復(fù)雜了。在棧中,自動(dòng)添加和刪除機(jī)制使得占用的內(nèi)存總是連續(xù)的,但new和delete的相互影響可能導(dǎo)致占用的自由存儲(chǔ)區(qū)不連續(xù),這使得跟蹤新分配內(nèi)存的位置更加困難。
8.4棧、堆和內(nèi)存泄漏
如果使用new運(yùn)算符在自由存儲(chǔ)空間(或堆)上創(chuàng)建變量后,沒(méi)有調(diào)用delete,則即使包含指針的內(nèi)存由于作用域規(guī)則和對(duì)象生命周期的原因而被釋放,在自由存儲(chǔ)空間上動(dòng)態(tài)分配的變量或結(jié)構(gòu)也將繼續(xù)存在。實(shí)際上,將會(huì)無(wú)法訪(fǎng)問(wèn)自由存儲(chǔ)空間中的結(jié)構(gòu),因?yàn)橹赶蜻@些內(nèi)存的指無(wú)效。這將會(huì)導(dǎo)致內(nèi)存泄漏。被泄漏的內(nèi)存將在程序的整個(gè)生命周期內(nèi)都不可使用;這些內(nèi)存被分配出去,但無(wú)法收回。
九、數(shù)組的替代品
模板類(lèi)vector和array是數(shù)組的替代品。
1、模板類(lèi)vector
模板類(lèi)vector類(lèi)似于string類(lèi),也是一種動(dòng)態(tài)數(shù)組。可以在運(yùn)行階段設(shè)vector對(duì)象的長(zhǎng)度,也可以在末尾添加數(shù)據(jù),還可在中間插入數(shù)據(jù)?;旧?,它是使用new創(chuàng)建動(dòng)態(tài)數(shù)組的替代品。實(shí)際上,vector類(lèi)確實(shí)使用new和delete來(lái)管理內(nèi)存,但這種工作是自動(dòng)完成的。
要使用vector對(duì)象,必須要包含頭文件vector。其次vector包含在名稱(chēng)空間std種,因此需要使用using編譯指令;第三,模板使用不同的語(yǔ)法來(lái)指出它存儲(chǔ)的數(shù)據(jù)類(lèi)型;第四,vector類(lèi)使用不同的語(yǔ)法來(lái)指定元素?cái)?shù)。其中n_elem可以是變量。
如:vector<typename> vt(n_elem);
Vt是一個(gè)vector<typename> 對(duì)象。
由于vector對(duì)象在您插入或添加值時(shí)自動(dòng)調(diào)整長(zhǎng)度,因此可以將vt的初始長(zhǎng)度設(shè)置為零。但要調(diào)整長(zhǎng)度,需要使用vector包種的各種方法。
2、模板類(lèi)array
Vector類(lèi)的功能比數(shù)組強(qiáng)大,但付出的代價(jià)是效率稍低。如果您需要的是長(zhǎng)度固定的數(shù)組,使用數(shù)組是更佳的選擇,但代價(jià)是不那么方便和安全。因此,使用array模板類(lèi),array對(duì)象的長(zhǎng)度也是固定的,也使用棧,而不是自由存儲(chǔ)區(qū),因此其效率與數(shù)組相同,但更方遍和安全。
創(chuàng)建array對(duì)象,需要包含頭文件array。Array對(duì)象的創(chuàng)建語(yǔ)法與vector稍有不同。
vector<typename,n_elem> arr;
其中n_elem不能是變量。
————————————————
版權(quán)聲明:本文為CSDN博主「好學(xué)的小李」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zjnldxshsj/article/details/80698687