C++復(fù)合類型 (CPP Chapter4)

基于基本類型和浮點(diǎn)類型創(chuàng)建(C語言:派生類型)

1.數(shù)組(簡(jiǎn)介)

1.數(shù)組聲明?? ·存儲(chǔ)在每個(gè)元素中的值的類型? ·數(shù)組名 ? ·數(shù)組中的元素量

??????????????????? typeName? arrayName[arraySize];

2.數(shù)組初始化 C++11初始化? ·可省略等號(hào)·大括號(hào)不包含任何東西所有元素置為零·列表初始化禁止窄縮轉(zhuǎn)換

3.C++標(biāo)準(zhǔn)模板庫(STL)提供了一種數(shù)組代替品——模板類vector

2.字符串

C++處理字符串的方式有兩種除破,第一種來自C語言赃份,C-風(fēng)格字符串,另一種基于string類庫的方法

1.初始化??? ·數(shù)組初始化 '\0'? ·字符串常量(字符串字面值)

2.處理字符串的函數(shù)根據(jù)空字符的位置洋丐,而不是數(shù)組長度來進(jìn)行處理,C++對(duì)字符串長度沒有限制

?? sizeof運(yùn)算符指出整個(gè)數(shù)組的長度虹曙,strlen()函數(shù)返回的是存儲(chǔ)在數(shù)組中的字符串的長度惑芭,而不是數(shù)組本身的長度,此外泵三,strlen()只計(jì)算可見的字符串,不把空字符計(jì)算在內(nèi)

3. cin使用空白來確定字符串的結(jié)束位置集漾,這意味著cin 在獲取字符串輸入時(shí)只讀取一個(gè)單詞 (cin的高級(jí)特性)

4.面向行的輸入:getline()

??? istream類切黔,getline()函數(shù)讀取整行,它使用通過回車鍵輸入的換行符來確定輸入結(jié)尾?

??? 調(diào)用: cin.getline()

??? 參數(shù):有兩個(gè)參數(shù)具篇,第一個(gè)參數(shù)用來存儲(chǔ)輸入行的數(shù)組的名稱纬霞,第二個(gè)參數(shù)是要讀取的字符數(shù)。getline成員函數(shù)在讀取指定數(shù)目的字符或遇到換行符時(shí)停止讀取

???? getline()函數(shù)每次讀取一行驱显,它通過換行符來確定行尾诗芜,但不保存換行符瞳抓。相反,在存儲(chǔ)字符串時(shí)伏恐,它用空字符來替換換行符

5.面向行的輸入:get()

??? istream類孩哑,該函數(shù)有幾種變體,其中一種變體的工作方式與getline相似翠桦,接受的參數(shù)相同横蜒,解釋參數(shù)的方式也相同,但是不在讀取并丟棄換行符销凑,而是將其留在輸入隊(duì)列中丛晌。如果不使用幫助get()不能跨過該換行符

?? 另一種變體,不帶參數(shù)的cin.get()斗幼,調(diào)用讀取下一個(gè)字符(處理換行符)

?? 另一種使用方式是將兩個(gè)類成員函數(shù)拼接起來(合并)

?? cin.get(name. Arsize).get();

?? cin.get(name, Arsize).getline(name2, Arsize);

?? cin.get(name, Arsize)返回一個(gè)cin對(duì)象澎蛛,該對(duì)象隨后將被用來調(diào)用get()函數(shù)

?? C++允許函數(shù)有多個(gè)版本,條件是這些版本的參數(shù)列表不同——函數(shù)重載

6.老式實(shí)現(xiàn)沒有g(shù)etline()蜕窿,get()使輸入更仔細(xì)谋逻,例如,假設(shè)用get()將一行讀入數(shù)組中桐经,如何知道停止讀取的原因是 由于已經(jīng)讀取了整行毁兆,而不是由于數(shù)組已填滿。查看下一個(gè)輸入字符次询,如果是換行符荧恍,說明已經(jīng)讀取了整行瓷叫,否則屯吊,說明該行中還有其他輸入。(17章updateing)getline()使用簡(jiǎn)單摹菠,但get()使得檢查錯(cuò)誤更簡(jiǎn)單些

7.空行和其他問題(5章盒卸,6章, 17章updating)?? p81

?? 當(dāng)getline()或get()讀取空行時(shí)次氨,將發(fā)生什么

?? 當(dāng)get()讀取空行后將設(shè)置失效位(failbit)這意味著接下來的輸入將被阻斷蔽介,但可以用cin.clear()恢復(fù)輸入

?? 另一個(gè)問題是,輸入行包含的字符數(shù)比指定的多煮寡,getline()和get()將把余下的字符留在輸入隊(duì)列之中虹蓄,而getline()還會(huì)設(shè)置失效位,并關(guān)閉后面的輸入

8.混合輸入字符串和數(shù)字

??? 混合輸入數(shù)字和面向行的字符串會(huì)導(dǎo)致問題幸撕,讀取數(shù)字后薇组,回車鍵生成的換行符留在了輸入隊(duì)列中,讀取面向行的字符串前應(yīng)先讀取并丟棄換行符

??? cin.get();

??? cin.get(ch);

3.String類 (簡(jiǎn)介)

?????? 使用string類的對(duì)象來存儲(chǔ)字符串坐儿,string類使用比數(shù)組簡(jiǎn)單律胀,提供了將字符串作為一種數(shù)據(jù)類型的表示方法宋光。使用string類要在頭文件中包含頭文件string,string類位于名稱空間std中

1.與C-風(fēng)格字符串異同

??? ·可以使用C-風(fēng)格字符串來初始化string對(duì)象

??? ·可以使用cin將鍵盤輸入存儲(chǔ)到string對(duì)象中炭菌,cout來顯示string對(duì)象

??? ·可以使用數(shù)組表示法來訪問存儲(chǔ)法來訪問存儲(chǔ)在string對(duì)象中的字符

??? ·最主要區(qū)別是罪佳,可以將string對(duì)象聲明為簡(jiǎn)單變量,而不是數(shù)組黑低,類設(shè)計(jì)讓程序可以自動(dòng)處理string的大小赘艳。這使得與使用數(shù)組相比,使用string對(duì)象更方便克握,也更安全第练。從理論上說,可以將char數(shù)組視為一組用于存儲(chǔ)一個(gè)字符串的char存儲(chǔ)單元玛荞,而string類變量是一個(gè)表示字符串的實(shí)體

2.C++11字符串初始化

??? 允許將列表初始化用于C-風(fēng)格字符串和string對(duì)象

??? string str1? {"Hello World!"};

3.string類的操作

??? 不能將一個(gè)數(shù)組賦給另一個(gè)數(shù)組娇掏,但是可以將一個(gè)string對(duì)象賦給另一個(gè)string對(duì)象

??? 可使用+/+=拼接兩個(gè)string對(duì)象

??? C-風(fēng)格字符串???? 頭文件cstring提供C語言庫中的函數(shù)

??????????????????? strcpy(charr1, charr2);??? //copy charr2 to charr1

??????????????????? strcat(charr1, charr2);??? //append contents of charr2 to char1

??????????????????? strncpy(charr1, charr2, n);

??????????????????? strncat(charr1, charr2, n);

??????????????????? 后兩個(gè)函數(shù)接收指出目標(biāo)數(shù)組最大允許長度的第三個(gè)參數(shù),因此更為安全

?????????????????? string類具有自動(dòng)調(diào)整大小的功能勋眯,能夠避免覆蓋相鄰內(nèi)存婴梧,數(shù)據(jù)破壞的事情發(fā)生

?????????????????? string str1;

?????????????????? char charr[20];

?????????????????? int len1 = str1.size();????????????????????? //類方法,方法是一個(gè)函數(shù)客蹋,只能通過其所屬類的對(duì)象進(jìn)行調(diào)用

?????????????????? int len2 = strlen(charr1);???????????? //常規(guī)函數(shù)塞蹭,接收一個(gè)C-風(fēng)格字符串為參數(shù),返回字符數(shù)

4.string類I/O

??? 未初始化的數(shù)組的內(nèi)容是未定義的讶坯,未被初始化的string對(duì)象的長度被自動(dòng)設(shè)置為零番电。

??? cin.getline(charr, 20);

??? getline(cin,? str1);???? /*不是一個(gè)類方法,istream中有處理double辆琅、int和其他基本類型的類方法漱办,但沒有處理string對(duì)象的類方法。將cin作為參數(shù)婉烟,指出到哪里去查找輸入娩井。沒有指出字符串長度的參數(shù),因?yàn)閟tring對(duì)象根據(jù)字符串的長度自動(dòng)調(diào)整自己的大小似袁。*/

?? cin >> x;????? //使用istream類的一個(gè)成員函數(shù)

?? cin >> str;??? //使用string類的一個(gè)友元函數(shù)?? (updating)

5.其他形式的字符串字面值

?? wchar_t? title[] = L''Chief Astrogator";????????????????? //wchar前綴?? L

?? char16_t name[]? = u"Felonia? Ripova";??????????????? //char16_t前綴? u

?? char32_t? car[]? =? U"Humber Super Snipe";??????? // char32_t前綴? U

? (unfinshed)

4.結(jié)構(gòu)(簡(jiǎn)介)

?? 結(jié)構(gòu)是一種比數(shù)組更靈活的數(shù)據(jù)格式洞辣,因?yàn)橥粋€(gè)結(jié)構(gòu)可以存儲(chǔ)多種類型的數(shù)據(jù)。

?? 結(jié)構(gòu)是用戶定義的類型昙衅,而結(jié)構(gòu)聲明定義了這種類型的數(shù)據(jù)屬性扬霜。定義了類型后,便可以創(chuàng)建這種類型的變量而涉。創(chuàng)建結(jié)構(gòu)包括兩步著瓶,首先,定義結(jié)構(gòu)描述——它描述并標(biāo)記了能夠存儲(chǔ)在結(jié)構(gòu)中的各種數(shù)據(jù)類型婴谱。然后按照描述創(chuàng)建結(jié)構(gòu)變量(結(jié)構(gòu)數(shù)據(jù)對(duì)象)蟹但。

?? struct? inflatable

?? {

???????? char name[];????????????????? //結(jié)構(gòu)的成員 躯泰, 聲明語句

???????? float volume;

???????? double? price;

?? };

inflatable?? hat;??????? //inflatable類型的變量

C++允許在聲明結(jié)構(gòu)變量時(shí)省略關(guān)鍵字struct华糖,在C++中結(jié)構(gòu)標(biāo)記的用法與基本類型名相同麦向。訪問成員函數(shù)的方式是從訪問結(jié)構(gòu)成員變量(eg : hat.volume)的方式衍生而來的。

C++不提倡使用外部變量客叉,但提倡使用外部結(jié)構(gòu)聲明诵竭,另外,在外部聲明符號(hào)變量通常更合理

1.初始化

?? 和數(shù)組一樣兼搏,使用由逗號(hào)分割值列表卵慰,并將這些值用花括號(hào)擴(kuò)起。

?? C++結(jié)構(gòu)初始化??? 等號(hào)可選佛呻,其次裳朋,如果大括號(hào)內(nèi)未包含任何東西,各個(gè)成員都將被設(shè)置為零吓著,C-風(fēng)格字符串每個(gè)字節(jié)都被設(shè)置為零鲤嫡,最后,不允許縮窄轉(zhuǎn)換

?? 如果編譯器支持對(duì)以string對(duì)象作為成員的結(jié)構(gòu)進(jìn)行初始化绑莺,可以使用string對(duì)象而不是字符數(shù)組(std::string? str)

2.其他結(jié)構(gòu)屬性

?? C++使用戶自定義的類型與內(nèi)置類型盡可能相似暖眼。

?? 可以將結(jié)構(gòu)作為參數(shù)傳遞給函數(shù),可以返回一個(gè)結(jié)構(gòu)纺裁。

?? 可以使用賦值運(yùn)算符將結(jié)構(gòu)賦給另一個(gè)同類型的結(jié)構(gòu)诫肠,即使成員是數(shù)組,這種賦值被稱為成員賦值

?? (傳遞返回結(jié)構(gòu))

??? 可以同時(shí)完成定義結(jié)構(gòu)和創(chuàng)建結(jié)構(gòu)變量的工作欺缘,只需將變量名放在結(jié)束括號(hào)的后面即可栋豫。

?? ? struct? inflatable

?? {

???????? char name[];?????????????????

???????? float volume;

???????? double? price;

?? }hat,? key;????????????????????? //two variable

可以初始化這樣創(chuàng)建的變量

??? struct? inflatable

?? {

???????? char name[];?????????????????

???????? float volume;

???????? double? price;

?? }hat? =??

{

??????? "Key",

????? ?? 6.0,

????? ?? 8.7,

};?????????????

還可以聲明沒有名稱的結(jié)構(gòu)類型,方法是省略名稱浪南,同時(shí)定義一種結(jié)構(gòu)類型和一個(gè)這種類型的變量笼才。

struct

?? {

???????? char name[];?????????????????

???????? float volume;

???????? double? price;

?? } key;

這樣將創(chuàng)建一個(gè)名為key的結(jié)構(gòu)變量,可以使用成員運(yùn)算符來訪問它的成員络凿,但這種類型沒有名稱,因此以后無法創(chuàng)建這種類型的變量昂羡。 ?????????????

與C結(jié)構(gòu)不同絮记,C++結(jié)構(gòu)除了成員變量之外,還可以有成員函數(shù)虐先,但這些高級(jí)特性通常被用于類中怨愤,而不是結(jié)構(gòu)中。(Updating)

3.結(jié)構(gòu)數(shù)組

可以創(chuàng)建元素為結(jié)構(gòu)的數(shù)組

初始化:結(jié)合初始化數(shù)組和初始化結(jié)構(gòu)的規(guī)則

4.結(jié)構(gòu)中的位字段

與C語言一樣蛹批,C++也允許指定占用特定位數(shù)的結(jié)構(gòu)成員撰洗,這使得創(chuàng)建與某個(gè)硬件設(shè)備上的寄存器對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)非常方便篮愉。字段的類型應(yīng)為整型或枚舉。冒號(hào)后面是一個(gè)整數(shù)差导,指定了使用的位數(shù)试躏。可以使用沒有名稱的字段來提供間距设褐,每個(gè)成員都被稱為位字段颠蕴。

struct? torgle

{

unsigned int? SN :?? 4;

unsigned? int :? 4;???????? //4bits? unused

bool?? goodIn? :?? 1;

}

可使用標(biāo)準(zhǔn)的結(jié)構(gòu)表示法來訪問位字段。

位字段通常用在低級(jí)編程中助析,一般來說犀被,可以使用整型和按位運(yùn)算符來代替這種方式。(附錄E?? updating)

5.共用體

共用體(union)是一種數(shù)據(jù)格式外冀,它能存儲(chǔ)不同的數(shù)據(jù)類型寡键,但只能同時(shí)存儲(chǔ)其中的一種類型。

union? one

{

int?? int_val ;

long?? long_val;

double?? double_val;

};

one? pail;

pail.int_val ? = ? 35;

cout << pail.int_val;

pail.double_val? =? 98.75;

cout<<pail.double_val;

共用體的長度為其最大成員的長度雪隧,共用體的用途之一是昌腰,當(dāng)數(shù)據(jù)項(xiàng)使用兩種或更多格式但不會(huì)同時(shí)使用時(shí),可節(jié)省空間膀跌。

匿名共用體沒有名稱遭商,其成員將成為位于相同地址處的變量

struct? widget

{

char?? brand[];

int?? type;

union

??? {

??????????? long??? id_num;

??????????? double? id_char[];

??? };

};

widget prize;

if(prize.type?? ==?? 1)

?????????? cin>>prize.id_num;

?else

?????????? cin>>prize.id_char;

共用體常用于節(jié)省內(nèi)存,此外捅伤,共用體常用于操作系統(tǒng)數(shù)據(jù)結(jié)構(gòu)或硬件數(shù)據(jù)結(jié)構(gòu)劫流。

6.枚舉

C++的enum提供了另一種創(chuàng)建符號(hào)常量的方式,這種方式可以代替const丛忆,它還允許定義新類型祠汇,但必須按嚴(yán)格的限制執(zhí)行。

enum spectrum {red,? orange,? yellow,? greeen, blue,? violet,? indigo,? ultraviolet};

這條語句中熄诡,spectrum成為新類型的名稱:枚舉可很,將red,yellow等作為符號(hào)常量凰浮,他們對(duì)應(yīng)整數(shù)值0-7我抠,這些常量叫做枚舉量。在默認(rèn)的情況下袜茧,將整數(shù)值賦給枚舉量菜拓,第一個(gè)枚舉量的值為0,第二個(gè)為1笛厦,以此類推可以通過顯式的指定整數(shù)值來覆蓋默認(rèn)值纳鼎,在不進(jìn)行強(qiáng)制性類型轉(zhuǎn)化的情況下,只能將定義枚舉時(shí)使用的枚舉量賦給這種枚舉的變量。spectrum變量只有八個(gè)可能的值贱鄙,為了獲得最大程度的可移植性劝贸,應(yīng)將把非enmu值賦給enum變量視為錯(cuò)誤(有些編譯器出現(xiàn)錯(cuò)誤,有些編譯器警告)逗宁。

對(duì)于枚舉映九,只定義了賦值運(yùn)算符,沒有為枚舉定義算術(shù)運(yùn)算疙剑。(有些實(shí)現(xiàn)沒有這種限制氯迂,這有可能導(dǎo)致反類型限制)

spectrum?? band;

band = blue;

枚舉量是整型,可被提升為int類型言缤,但int類型不能自動(dòng)轉(zhuǎn)化為枚舉類型嚼蚀。(可將枚舉賦給int,但不能把int類型賦給枚舉類型管挟,有些實(shí)現(xiàn)沒有這種限制)枚舉可以轉(zhuǎn)換為int類型轿曙,因此可以在算數(shù)表達(dá)式中同時(shí)使用枚舉和常規(guī)整數(shù),盡管并沒有為枚舉本身定義算數(shù)運(yùn)算僻孝。

band? =? orange? +? red导帝;?? //? not? valid.? 相當(dāng)于將一個(gè)int類型賦給枚舉量

如果int值有效,則可以通過強(qiáng)制類型轉(zhuǎn)換穿铆,將它賦給枚舉變量:

band? = spectrum(3);

如果將一個(gè)不適當(dāng)?shù)闹颠M(jìn)行強(qiáng)制類型轉(zhuǎn)換您单,結(jié)果是不確定的,這么做不會(huì)出錯(cuò)荞雏,但結(jié)果不可用虐秦。

枚舉常被用來定義相關(guān)的符號(hào)常量,而不是新的類型凤优,如果只打算使用常量悦陋,而不創(chuàng)建枚舉類型的變量,則可省略枚舉類型的名稱

enum{ red,? orange,? yellow,? greeen, blue,? violet,? indigo,? ultraviolet }

1.設(shè)置枚舉量的值

??? 可以使用賦值運(yùn)算符來顯式地設(shè)置枚舉量的值筑辨,指定的值必須是整數(shù)俺驶,也可以只顯式地定義其中一些枚舉量的值,后面沒有被初始化的枚舉量的值將比其前面的枚舉量大1棍辕,可以創(chuàng)建多個(gè)值相同的枚舉量暮现。在C++早期版本中只能將int值(或提升成int的值)賦給枚舉量,但這種限制取消了痢毒,因此可以使用long甚至longlong類型的值送矩。

2.枚舉的取值范圍

??? 最初對(duì)于枚舉來說,只有聲明中指出的那些值是有效的哪替,然而,C++現(xiàn)在通過強(qiáng)制類型轉(zhuǎn)換菇怀,增加了可賦給枚舉變量的合法值凭舶。每個(gè)枚舉變量都有取值范圍(range)晌块,通過強(qiáng)制類型轉(zhuǎn)換,可以將取值范圍內(nèi)的任何整數(shù)值賦給枚舉變量帅霜,即使這個(gè)值不是枚舉值匆背。

???? 取值范圍如下

???? 上限:找到枚舉量的最大值,找到大于這個(gè)最大值的身冀、最小的2的冪钝尸,將它減去1,得到的便是取值范圍的上限

????? 下限:找到枚舉量的最小值搂根,如果它不小于0珍促,則取值下限為0;否則剩愧,與上限方式相同猪叙,但加上負(fù)號(hào);

????? 選擇用多少空間來存儲(chǔ)枚舉由編譯器決定仁卷,對(duì)于取值范圍較小的枚舉穴翩,使用一個(gè)字節(jié)或更小的空間,而對(duì)于包含long類型值的枚舉锦积,則使用4個(gè)字節(jié)芒帕。

3.

??? C++11擴(kuò)展了枚舉,增加了作用域內(nèi)枚舉


7.指針(指針丰介、數(shù)組背蟆、自由存儲(chǔ)空間)

(此部分內(nèi)容整合進(jìn)C++專項(xiàng)中,C++數(shù)組和C++指針基矮。)

計(jì)算機(jī)程序在存儲(chǔ)數(shù)據(jù)中必須跟蹤的三種基本屬性:

·信息存儲(chǔ)在何處

·存儲(chǔ)的值為多少

·存儲(chǔ)的值是什么類型

定義一個(gè)簡(jiǎn)單變量時(shí)淆储,聲明語句指出了值的類型和符號(hào)名,還讓程序?yàn)橹捣峙鋬?nèi)存家浇,并在內(nèi)部跟蹤該內(nèi)存單元本砰。使用常規(guī)變量時(shí),值是指定的量钢悲,而地址為派生量点额。使用指針策略時(shí),將地址視為指定的量莺琳,而將值視為派生量还棱。指針是C++內(nèi)存管理編程理念的核心。

指針與C++基本原理:??????????? 面向?qū)ο缶幊膛c傳統(tǒng)的過程性編程的區(qū)別在于惭等,OOP強(qiáng)調(diào)的是在運(yùn)行階段而不是編譯階段做決策珍手。運(yùn)行階段決策提供了靈活性。在運(yùn)行階段做決策并非OOP獨(dú)有的,但使用C++編寫這樣的代碼比使用C簡(jiǎn)單琳要。

例如:為數(shù)組分配內(nèi)存時(shí)寡具,聲明數(shù)組,指定數(shù)組長度為編譯階段決策稚补;使用OOP時(shí)童叠,在運(yùn)行階段決定數(shù)組的長度。為使用這種方法课幕,語言必須允許在程序運(yùn)行時(shí)創(chuàng)建數(shù)組厦坛,C++采用的方法是,使用關(guān)鍵字new請(qǐng)求正確數(shù)量的內(nèi)存以及使用指針跟蹤新分配的內(nèi)存的位置乍惊。

1.聲明和初始化指針

?? typename? *?? pointerName;

??? int*? ptr;???????????????????? //在C++中杜秸,int*是一種類型——指向int的指針

??? int* ptr1,? ptr2;??????? //創(chuàng)建一個(gè)指針,和一個(gè)int變量污桦。對(duì)每個(gè)指針變量名亩歹,都需要使用一個(gè)*

??? 和數(shù)組一樣,指針都是基于其他類型的

??? 在聲明語句中初始化指針凡橱,被初始化的時(shí)指針小作,而不是它指向的值

??? int higgens = 5;

??? int*? ptr? =? &higgens;

??? 指針的危險(xiǎn):???? 在C++中創(chuàng)建指針時(shí),計(jì)算機(jī)將分配用來儲(chǔ)存地址的內(nèi)存稼钩,但不會(huì)分配用來存儲(chǔ)指針?biāo)赶虻臄?shù)據(jù)的內(nèi)存顾稀。使用指針時(shí),先初始化坝撑,再解引用静秆。

??? 指針不是整型,雖然計(jì)算機(jī)通常把地址當(dāng)作整數(shù)來處理巡李。不能簡(jiǎn)單地將整數(shù)賦給指針抚笔,要將數(shù)字值作為地址來使用,應(yīng)通過強(qiáng)制類型轉(zhuǎn)換將數(shù)字轉(zhuǎn)換為適當(dāng)?shù)牡刂奉愋停?/p>

???? int*? ptr;

???? ptr = (int*) 0xB8000000;

???? ptr是int值的地址并不意味著ptr本身的類型是int

2.使用new來分配內(nèi)存(使用指針來管理運(yùn)行階段的內(nèi)存空間分配)

??? 指針真正的用武之地在于 : 在運(yùn)行階段分配未命名的內(nèi)存以存儲(chǔ)值侨拦。在這種情況下殊橙,只能通過指針來訪問內(nèi)存

??? 在C語言中,可以用庫函數(shù)malloc()來分配內(nèi)存狱从;在C++仍然可以這樣做膨蛮,但還有更好的方法——new運(yùn)算符

? ? 在運(yùn)行階段為一個(gè)int值分配未命名的內(nèi)存,并使用指針來訪問這個(gè)值季研。要告訴new需要為哪種數(shù)據(jù)類型分配內(nèi)存敞葛;new將找到一個(gè)長度正確的內(nèi)存塊,并返回其地址与涡,將該地址賦給一個(gè)指針惹谐。

??? typeName*? pointer_name? =? new ? typeName;????????? //為一個(gè)數(shù)據(jù)對(duì)象獲得并指定分配內(nèi)存的通用格式

??? 該pointer指向一個(gè)數(shù)據(jù)對(duì)象持偏,"數(shù)據(jù)對(duì)象"比"變量"更通用,它指的是為數(shù)據(jù)項(xiàng)分配的內(nèi)存塊豺鼻。

??? 處理數(shù)據(jù)對(duì)象的指針方法使程序在管理內(nèi)存方面有更大的控制權(quán)综液。

??? new分配的內(nèi)存塊通常與常規(guī)變量聲明分配的內(nèi)存塊不同款慨,常規(guī)聲明的變量都存儲(chǔ)在被稱為棧(stack)的內(nèi)存區(qū)域中儒飒;而new從被稱為堆(heap)或自由存儲(chǔ)區(qū)(free store)的內(nèi)存區(qū)域分配內(nèi)存。

??? 計(jì)算機(jī)可能會(huì)由于沒有足夠的內(nèi)存而無法滿足new的請(qǐng)求檩奠,這種情況下桩了,new通常會(huì)引發(fā)異常(錯(cuò)誤處理),在較老的實(shí)現(xiàn)中埠戳,new將返回0. 在C++中井誉,值為0的指針被稱為空指針(null? pointer)。C++確闭福空指針不會(huì)指向任何有效的數(shù)據(jù)颗圣,因此它常被用來表示運(yùn)算符或函數(shù)失敗,如果成功屁使,將返回一個(gè)有用的指針在岂。可檢測(cè)處理分配內(nèi)存失敗蛮寂。

3.使用delete釋放內(nèi)存

??? 當(dāng)需要內(nèi)存時(shí)蔽午,可以使用new來請(qǐng)求,這只是C++內(nèi)存管理數(shù)據(jù)包中有魅力的一個(gè)方面酬蹋,另一個(gè)方面是delete運(yùn)算符及老,它使得在使用完內(nèi)存后,能夠?qū)⑵錃w還給內(nèi)存池這是通向最有效的使用內(nèi)存的關(guān)鍵一步范抓。歸還獲釋放的內(nèi)存可供程序的其他部分使用骄恶。

????? in*? ps? =?? new? int;

????? delete ps;

???? · 這將釋放ps指向的內(nèi)存,但不會(huì)刪除指針ps本身匕垫。

???? ·要配對(duì)的使用new和delete僧鲁,否則將發(fā)生內(nèi)存泄漏,也就是說年缎,被分配的內(nèi)存再也無法使用了悔捶。如果內(nèi)存泄漏嚴(yán)重,則程序?qū)⒂捎诓粩鄬ふ腋鄡?nèi)存而終止单芜。

????? ·不要釋放已經(jīng)釋放的內(nèi)存塊蜕该,C++標(biāo)準(zhǔn)指出,這樣做的結(jié)果是不確定的洲鸠,這意味著什么情況都有可能發(fā)生堂淡。

????? ·不能使用delete來釋放聲明變量所獲得的內(nèi)存

????? ·只能用delete來釋放使用new分配的內(nèi)存馋缅。然而,對(duì)空指針使用delete是安全的

????? ·使用delete的關(guān)鍵在于绢淀,將它用于new分配的內(nèi)存萤悴。這并不意味著要使用用于new的指針,而是用于new的地址

????? ·不要?jiǎng)?chuàng)建兩個(gè)指向同一個(gè)內(nèi)存塊的指針皆的,這將增加錯(cuò)誤地刪除同一個(gè)內(nèi)存塊兩次的可能性

4.使用new來創(chuàng)建動(dòng)態(tài)數(shù)組

????? 通常覆履,對(duì)于大型數(shù)據(jù)(如數(shù)組,字符串和結(jié)構(gòu))费薄,應(yīng)使用new硝全。

???? 編譯時(shí)給數(shù)組分配內(nèi)存被稱為靜態(tài)聯(lián)編,但使用new時(shí)楞抡,如果在運(yùn)行階段需要數(shù)組伟众,則創(chuàng)建它,如果不需要召廷,則不創(chuàng)建凳厢。還可以在程序運(yùn)行時(shí)選擇數(shù)組的長度,這被稱為動(dòng)態(tài)聯(lián)編竞慢。這種數(shù)組被稱為動(dòng)態(tài)數(shù)組先紫。

1.使用new創(chuàng)建動(dòng)態(tài)數(shù)組

??? int*? psome? = new? int[100];

??? new運(yùn)算符返回第一個(gè)元素的地址

??? 當(dāng)程序使用完new分配的內(nèi)存塊時(shí)梗顺,應(yīng)使用delete釋放它們

??? delete[]?? psome泡孩;???????????????????? //格式匹配

??? psome是指向一個(gè)int的指針,必須讓程序跟蹤內(nèi)存塊中的元素個(gè)數(shù)寺谤,以便以后使用delete[]運(yùn)算符時(shí)能正確的釋放這些內(nèi)存仑鸥。但這些信息不是公用的,例如变屁,不能使用sizeof運(yùn)算符來確定動(dòng)態(tài)分配的數(shù)組包含的字節(jié)數(shù)

??? type_name?? *??? pointer_name?? =?? new?? type_name [num_elements];?? //通用格式

2.使用動(dòng)態(tài)數(shù)組

??? 將指針名當(dāng)作數(shù)組使用 ??

??? C和C++內(nèi)部都用指針來處理數(shù)組

??? 不能修改數(shù)組名的值眼俊,但是指針是變量,因此可以修改它的值粟关。

5.指針疮胖、數(shù)組和指針?biāo)銛?shù)

指針和數(shù)組基本等價(jià)的原因在于指針?biāo)銛?shù)(pointer-arithmetic)和C++內(nèi)部處理數(shù)組的方式。

在多數(shù)情況下闷板,C++將數(shù)組名解釋為數(shù)組第一個(gè)元素的地址澎灸。

指針變量加1,其增加的值等于指向的類型占用的字節(jié)數(shù)

通常遮晚,使用數(shù)組表示法(包括使用指針)性昭,C++將執(zhí)行以下轉(zhuǎn)換:

???????? arrayname[i]??? becomes? *(arrayname + i)

???????? pointername[i] ?? becomes ? *(arrayname + i)

因此,在很多情況下县遣,可以相同的方式使用指針名和數(shù)組名糜颠。對(duì)于它們汹族,可以使用數(shù)組方括號(hào)表示法,也可以使用解除引用運(yùn)算符其兴。在多數(shù)表達(dá)式中顶瞒,它們都表示地址。區(qū)別之一是元旬,可以修改指針的值榴徐,而數(shù)組名是常量。另一個(gè)區(qū)別是法绵,對(duì)數(shù)組應(yīng)用sizeof運(yùn)算符得到的是數(shù)組的長度箕速,而對(duì)指針應(yīng)用sizeof得到的是指針的長度,即使指針指向的是一個(gè)數(shù)組朋譬,這種情況下,C++不會(huì)將數(shù)組名解釋為地址兴垦。

數(shù)組的地址:????? 數(shù)組名被解釋為其第一個(gè)元素的地址徙赢,而對(duì)數(shù)組名應(yīng)用地址運(yùn)算符時(shí),得到的是整個(gè)數(shù)組的地址探越。

int? tell[10];

cout ? << ? tell ? <<? endl; ? ? ? ? ? ? //displays? &tell[0]

cout?? <<? &tell? <<? endl;?????????? // displays? address of whole? array

int (*pas)[10] = &tell;?????????????? //pas? points? to? array? of 10? int

int*? pas[10]??????????????????????????????? //an? array? of? pointer to?? int

1.對(duì)指針解除引用

?? 對(duì)指針解除引用意味著獲得指針指向的值狡赐,對(duì)指針應(yīng)用間接值運(yùn)算符,另一種對(duì)指針解除引用的方法是使用數(shù)組表示法钦幔,千萬不能對(duì)未被初始化為適當(dāng)?shù)刂返闹羔樈獬谩?/p>

2.指針?biāo)銛?shù)

??? C++允許將指針和整數(shù)相加枕屉,加1的結(jié)果等于原來的地址值加上指向的對(duì)象占用的總字節(jié)數(shù)。還可以將一個(gè)指針減去另一個(gè)指針鲤氢,獲得兩個(gè)指針的差搀擂。僅當(dāng)兩個(gè)指針指向同一個(gè)數(shù)組時(shí),這種運(yùn)算才有意義卷玉。

3.數(shù)組的動(dòng)態(tài)聯(lián)編和靜態(tài)聯(lián)編

?? 靜態(tài)聯(lián)編:使用數(shù)組聲明來創(chuàng)建數(shù)組哨颂,即數(shù)組的長度在編譯時(shí)設(shè)置

?? 動(dòng)態(tài)聯(lián)編:使用new[]運(yùn)算符創(chuàng)建數(shù)組,運(yùn)行時(shí)分配空間相种,其長度也在運(yùn)行時(shí)設(shè)置威恼。使用完這種數(shù)組,應(yīng)使用delete[]釋放其占用的內(nèi)存寝并。

4.數(shù)字表示法和指針表示法

6.指針和字符串

1.

數(shù)組和指針的特殊關(guān)系可以擴(kuò)展到C-風(fēng)格字符串

在C++中箫措,用引號(hào)括起的字符串像數(shù)組名一樣,也是第一個(gè)元素的地址

對(duì)于數(shù)組中的字符串衬潦,用引號(hào)括起的字符串常量以及指針?biāo)枋龅淖址锫幚淼姆绞绞且粯拥模紝鬟f它們的地址

字符串字面值是常量别渔,有些編譯器將字符串字面值視為只讀常量附迷,可以訪問惧互,但不能修改,如果試圖修改喇伯,將導(dǎo)致運(yùn)行階段錯(cuò)誤喊儡。最好使用const關(guān)鍵字(const指針)

有些編譯器只使用字符串字面值的一個(gè)副本來表示程序中所有的該字面值,C++不能保證字符串字面值被唯一的存儲(chǔ)。如果是以上情況稻据,將值讀入一個(gè)字符串艾猜,可能會(huì)影響被認(rèn)為是獨(dú)立的為位于其他地方的字符串。

在將字符串讀入程序時(shí)捻悯,應(yīng)使用已分配的內(nèi)存地址匆赃。該地址可以是數(shù)組名,也可以是new初始化的指針今缚,不要使用字符串常量或未被初始化的指針來接收輸入算柳。為避免這些問題,可以使用一個(gè)足夠大的char數(shù)組或使用std::string對(duì)象

2.如何獲得字符串的副本

首先姓言,需要分配內(nèi)存來存儲(chǔ)該字符串瞬项,可以通過聲明另一個(gè)數(shù)組或者使用new來完成。

ps = new? char[strlen(array) + 1]何荚;???????????????? //不會(huì)浪費(fèi)空間

不能將array直接賦給ps囱淋,這樣只能修改存儲(chǔ)在ps中的地址,從而失去程序訪問新分配內(nèi)存的唯一途徑餐塘,需要使用庫函數(shù)strcpy():

strcpy(ps,? array);

獲得array的兩個(gè)獨(dú)立副本妥衣,new在離animal數(shù)組很遠(yuǎn)的地方找到了所需的內(nèi)存空間。

strcpy/strncpy

7.使用new創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)

在運(yùn)行時(shí)創(chuàng)建數(shù)組優(yōu)于在編譯時(shí)創(chuàng)建數(shù)組戒傻,對(duì)于結(jié)構(gòu)也是如此税手。通過使用new,可以創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)

將new用于結(jié)構(gòu)由兩步構(gòu)成:創(chuàng)建結(jié)構(gòu)和訪問其成員稠鼻。

創(chuàng)建動(dòng)態(tài)結(jié)構(gòu)時(shí)冈止,不能將成員運(yùn)算符句點(diǎn)用于結(jié)構(gòu)名,因?yàn)檫@種結(jié)構(gòu)沒有名稱候齿,只知道它的地址熙暴。

C++專門為這種情況提供了一個(gè)運(yùn)算符:箭頭成員運(yùn)算符(->),可用于指向結(jié)構(gòu)的指針慌盯。

另一種訪問結(jié)構(gòu)成員的方法是周霉,如果ps是指向結(jié)構(gòu)的指針,則*ps就是被指向的值——結(jié)構(gòu)本身亚皂,因此(*ps).price是該結(jié)構(gòu)的price成員俱箱。C++的運(yùn)算符優(yōu)先規(guī)則要求使用括號(hào)。

8.自動(dòng)存儲(chǔ)灭必、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)

根據(jù)用于分配內(nèi)存的方法狞谱,C++有三種管理數(shù)據(jù)內(nèi)存的方式:自動(dòng)存儲(chǔ)乃摹、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)(自由存儲(chǔ)存儲(chǔ)空間、堆)跟衅,C++11新增了第四種類型——線程存儲(chǔ)孵睬。(9章)

1.自動(dòng)存儲(chǔ)

在函數(shù)內(nèi)部定義的常規(guī)變量使用自動(dòng)存儲(chǔ)空間,被稱為自動(dòng)變量伶跷,這意味著它們?cè)谒鶎俚暮瘮?shù)被調(diào)用的時(shí)候產(chǎn)生掰读,在該函數(shù)結(jié)束是消亡。實(shí)際上叭莫,自動(dòng)變量是一個(gè)局部變量蹈集,其作用域?yàn)榘拇a塊。

自動(dòng)變量通常存儲(chǔ)在中雇初。這意味著執(zhí)行代碼塊時(shí)拢肆,其中的變量將依次加入到棧中,而在離開代碼塊時(shí)抵皱,將按相反的順序釋放這些變量善榛,這被稱為先進(jìn)后出。因此呻畸,在程序執(zhí)行的過程中,棧將不斷的增大和縮小悼院。

2.靜態(tài)存儲(chǔ)

靜態(tài)存儲(chǔ)是整個(gè)程序執(zhí)行期間都存在的存儲(chǔ)方式伤为。是變量成為靜態(tài)的方式由兩種:一種是在函數(shù)外面定義它;另一種是使用關(guān)鍵字static据途。

在K&RC中绞愚,只能初始化靜態(tài)數(shù)組和靜態(tài)結(jié)構(gòu),而C++Release2.0及后續(xù)版本和ANSIC中颖医,也可以初始化自動(dòng)數(shù)組和自動(dòng)結(jié)構(gòu)位衩。然而,有些C++實(shí)現(xiàn)還不支持對(duì)自動(dòng)數(shù)組和自動(dòng)結(jié)構(gòu)的初始化熔萧。

自動(dòng)存儲(chǔ)和靜態(tài)存儲(chǔ)的關(guān)鍵在于糖驴,這些方法嚴(yán)格地限制了變量的壽命。

3.動(dòng)態(tài)存儲(chǔ)

new和delete提供了一種比自動(dòng)和靜態(tài)變量更靈活的方法佛致。它們管理了一個(gè)內(nèi)存池贮缕,這在C++中被成為自由存儲(chǔ)空間或堆。該內(nèi)存池同用于靜態(tài)變量和自動(dòng)變量的內(nèi)存是分開的俺榆。數(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)存的位置更困難。

4.棧层玲、堆和內(nèi)存泄漏

8.類型組合

9.數(shù)組的代替品

模板類vector/array(C++11)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末号醉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辛块,更是在濱河造成了極大的恐慌畔派,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件润绵,死亡現(xiàn)場(chǎng)離奇詭異线椰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)尘盼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門憨愉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卿捎,你說我怎么就攤上這事配紫。” “怎么了午阵?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵躺孝,是天一觀的道長。 經(jīng)常有香客問我底桂,道長植袍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任籽懦,我火速辦了婚禮于个,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暮顺。我一直安慰自己厅篓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布拖云。 她就那樣靜靜地躺著贷笛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宙项。 梳的紋絲不亂的頭發(fā)上乏苦,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼汇荐。 笑死洞就,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的掀淘。 我是一名探鬼主播旬蟋,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼革娄!你這毒婦竟也來了倾贰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤拦惋,失蹤者是張志新(化名)和其女友劉穎匆浙,沒想到半個(gè)月后褪迟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芋酌,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年陆爽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了言秸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片软能。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖举畸,靈堂內(nèi)的尸體忽然破棺而出查排,到底是詐尸還是另有隱情,我是刑警寧澤抄沮,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布雹嗦,位于F島的核電站,受9級(jí)特大地震影響合是,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锭环,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一聪全、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辅辩,春花似錦难礼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撩鹿,卻和暖如春谦炬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工键思, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留础爬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓吼鳞,卻偏偏與公主長得像看蚜,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赔桌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 淺談C++常用輸入輸出 在編寫C++程序的時(shí)候供炎,經(jīng)常因?yàn)檩斎胼敵鲱^疼,所以在這里做一個(gè)小結(jié)疾党,記錄一下常用的輸入輸出...
    MinoyJet閱讀 3,749評(píng)論 0 6
  • 第一章 計(jì)算機(jī)與C++編程簡(jiǎn)介 C++程序6個(gè)階段編程 ->預(yù)處理->編譯->連接->裝入->執(zhí)行1.程序在編譯器...
    rogertan30閱讀 3,849評(píng)論 0 1
  • C/C++輸入輸出流總結(jié) 前兩天寫C++實(shí)習(xí)作業(yè)音诫,突然發(fā)現(xiàn)I/O是那么的陌生,打了好長時(shí)間的文件都沒有打開仿贬,今天終...
    LuckTime閱讀 1,732評(píng)論 0 6
  • 一纽竣、Java 簡(jiǎn)介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計(jì)...
    子非魚_t_閱讀 4,190評(píng)論 1 44
  • 希望你能快點(diǎn)長大,在我還能等待你的日子里茧泪,我喜歡和你嬉鬧蜓氨,喜歡和你瘋耍,但我卻知道最終會(huì)選擇的不是一位玩伴队伟,我需要...
    免辣閱讀 145評(píng)論 0 0