基于基本類型和浮點(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)