第4章 數(shù)組、指針與引用
4.1 數(shù)組
1一維數(shù)組
(1)一維數(shù)組的定義
一維數(shù)組是由具有一個下標的數(shù)組元素組成的數(shù)組,其定義形式如下:
<數(shù)據(jù)類型><數(shù)組名>[<數(shù)組長度>];
在此,<數(shù)據(jù)類型>是類型說明符,<數(shù)組名>是數(shù)組的名字,<數(shù)組長度>是任一值為正整數(shù)的int型常量表達式。<數(shù)組長度>用來指定數(shù)組中元素的個數(shù),即數(shù)組的大小,數(shù)組元素的下標是從0到<數(shù)組長度>-1。
(2)一維數(shù)組初始化
與所有的基本數(shù)據(jù)類型相同,數(shù)組也可以在時初始化。
當數(shù)組聲明沒有給出數(shù)組的大小,但是有初始化列表時,數(shù)組的大小就由列表中元素的個數(shù)來確定。
在定義數(shù)組時,可以不必給出所有數(shù)組元素的初始值,即在定義時部分地初始化數(shù)組。
(3)訪問數(shù)組元素
訪問數(shù)組元素的語法形式是:
<數(shù)組名>[<表達式>]
在此,<表達式>是非負的int型表達式,稱為下標。下標用于指定所要訪問的數(shù)組中元素的位置。在C+ +中,[]是一個運算符,稱為下標運算符。數(shù)組下標從0開始,長度為n的數(shù)組,其下標的范圍是0到n-1。在數(shù)組定義以后,給數(shù)組賦值時,必須一個元素一個元素的逐個訪問。
2二維數(shù)組
以行和列(即二維)形式排列的固定數(shù)目元素的集合,并且組成數(shù)組的每個元素的類型都相同,即帶有兩個下標的數(shù)組。
(1)二維數(shù)組的定義
定義二維數(shù)組的語法是:
<數(shù)據(jù)類型><數(shù)組名>[<表達式1>][<表達式2>];
在此<表達式1>和<表達式2>是值為正整數(shù)的常量表達式。表達式<表達式1>和<表達式2>,分別用來指定數(shù)組中行和列的數(shù)目。
(2)二維數(shù)組初始化
與一維數(shù)組相同,二維數(shù)組也可以在定義時初始化。
在定義時初始化二維數(shù)組要注意:
①所有在一行中的元素可以用花括號括起來,并且用逗號分隔;
、趯τ跀(shù)字類型數(shù)組,如果給定的數(shù)值不夠,則沒有指定數(shù)值的元素將初始化為0。此時,至少應有一個值來初始化二維數(shù)組。
③當數(shù)組聲明時沒有給出第一維的大小,但是有初始化列表時,第一維的大小就由列表中子列表的個數(shù)來確定。
(3)訪問二維數(shù)組元素
若要訪問二維數(shù)組的元素,必須要給出兩個下標:一個行下標和一個列下標。訪問二維數(shù)組元素的語法是:
<數(shù)組名>[<表達式1>][表達式2];
這里<表達式1>和<表達式2>是值為非負整數(shù)的表達式。<表達式1>指定行下標,<表達式2>指定列下標。
(3)多維數(shù)組
在C+ +中,對數(shù)組維數(shù)沒有限制。下面是對數(shù)組的通用定義。
以n維列表形式排列的固定數(shù)目元素的集合,稱為n維數(shù)組。定義n維數(shù)組的語法是:
<數(shù)據(jù)類型><數(shù)組名>[<表達式1>][<表達式2>]…[<表達式n>];
在此<表達式1>,<表達式2>,…<表達式n>都是值為正整數(shù)的常量表達式。
訪問n維數(shù)組元素的語法是:
<數(shù)組名>[<表達式1>][<表達式2>]…[<表達式n>];
在此<表達式1>,<表達式2>,…<表達式n>都是值為非負整數(shù)的表達式。<表達式i>(i=1,2,…,n)用來指定第i維元素的位置。
在將多維數(shù)組作為函數(shù)的形參時,可以不指定該數(shù)組中第一維的大小,但是必須指定該數(shù)組中其他維的大小。多維數(shù)組只可以作為引用參數(shù)傳遞給函數(shù),并且函數(shù)不能返回一個數(shù)組類型的返回值。C+ +對數(shù)組下標不做檢查。
4字符數(shù)組
(1)string類型與字符數(shù)組
string類型在ANSI/ISO標準C+ +頒布之前,標準C+ +庫并不提供string數(shù)據(jù)類型。string是一種用戶自定義的數(shù)據(jù)類型,它由C+ +標準庫來支持,而不是C+ +語言本身的一部分。在使用strign數(shù)據(jù)類型之前,需要在程序中包含頭文件string并聲明其所在的名字空間std。所有元素都是char類型的數(shù)組稱為字符數(shù)組。
字符數(shù)組有如下特點:
、贁(shù)組元素跟一般變量一樣可以賦值、比較、計算等。
、跀(shù)組下標也是從0~N-1(N為數(shù)組長度)。
③字符數(shù)組長度可以顯式給出,也可以隱式得到。
、苡呻p引號括起來的字符串常量具有靜態(tài)字符串數(shù)組類型。
、萦米址畬(shù)組初始化時,編譯程序以′\0′作為結(jié)束這個數(shù)組的標志。因此,數(shù)組長度至少要比字符串長度多1。
(2)常用字符串函數(shù)
C+ +提供了一系列字符串操作的函數(shù),這些函數(shù)都包含在頭文件cstring中。其中經(jīng)常會用到的字符串函數(shù)包括:strcpy(字符串拷貝,將一個字符串拷貝到另一個字符串變量中)、strcat(字符串連接,在字符串末端添加字符串)、strcmp(字符串比較,用來比較字符串)、strlen(字符串長度,用來求出字符串長度)、和strstr(字符串查找,在一個字符串中查找子串)。
、賡trcpy函數(shù)
調(diào)用strcpy()函數(shù)的一般形式為:
strcpy(to,from);
該函數(shù)將from字符串中的內(nèi)容復制到to字符串中。請記住,構(gòu)成to的字符串必須足夠大,以便保存包含在from中的字符串。否則,to字符串將會溢出,這很可能會導致系統(tǒng)崩潰。
、趕trcat函數(shù)
調(diào)用strcat()函數(shù)的一般形式為:
strcat(s1,s2);
該函數(shù)將字符串s2添加到字符串s1的末端;但并不修改字符串s2。必須確保字符串s1足夠大,以便保存它自己的內(nèi)容和字符串s2中的內(nèi)容。
、踫trcmp函數(shù)
調(diào)用strcmp()函數(shù)的一般形式為:
strcmp(s1,s2);
該函數(shù)比較兩個字符串,如果兩個字符串相等,返回0。如果字符串s1在字典順序上比字符串s2大,則返回一個正數(shù);如果比字符串s2小,則返回一個負數(shù)。
注意:函數(shù)strcmp比較兩個字符串時所采用的字典順序與真正意義上的字典順序還是有些差別的。實際上,它依次比較兩個字符串相應字符的編碼值(如ASCII碼值)來決定兩個字符串的大小。如,上面比較strcmp(″A″,″a″)的結(jié)果變?yōu)?1,因為字符′A′的編碼值為65,而字符′a′的編碼值為97,這與傳統(tǒng)意義上的字典順序不同。
④strlen函數(shù)
調(diào)用strlen()函數(shù)的一般形式為:
strlen(s);
該函數(shù)返回字符串s的長度,即字符串中字符的個數(shù)(不包括字符串結(jié)尾的′\ 0′)。
、輘trstr函數(shù)
調(diào)用strstr()函數(shù)的一般形式為:
strstr(s1,s2);
該函數(shù)在字符串s1中從左邊開始查找字符串s2,若查找成功則返回s2在s1中首次出現(xiàn)的位置,否則返回NULL,如果s2為″ ″,則返回s1。
4.2 指針
指針(即指針變量)是C+ +語言最大的功能之一。一個指針是一個特定類型數(shù)據(jù)的存儲地址,比如一個變量的地址。
與其他類型變量一樣,指針變量也必須要聲明。指針變量聲明的一般形式為:
<數(shù)據(jù)類型>*<變量名>;
其中,<數(shù)據(jù)類型>是指針所指對象的類型,在C+ +中可以指向任何C+ +類型。<變量名>是指針變量名。
指針使用兩種特殊的運算符——*和&。
一元(單目)運算符&用于返回其操作對象的內(nèi)存地址,其操作對象通常為一個變量名。例如:
ptr=&total;
把變量total的內(nèi)存地址存到指針變量ptr中。該地址是total變量在計算機內(nèi)存中的存儲地址。
第二個與指針相關(guān)的運算符是*,它與&運算符作用相反。作為一元運算符的*用于返回其操作數(shù)所指對象的值,因此,該運算符要求其操作對象為一個指針。
1指針和地址
(1)指針說明
從指針的定義可知,指針是用所指對象類型來表征的。在使用任何指針變量之前必須先給它賦一個所指合法具體對象的地址值。
如何使一個指針指向一個具體對象:
、偈褂胣ew運算符(或malloc和alloc等函數(shù))給指針分配一個具體空間。
②將另一個同類型的指針賦給它以獲得值。
、弁ㄟ^&運算符指向某個對象。
(2)指針運算
盡管指針中存放的是變量的地址,但在C+ +中指針只能進行如下運算。
、僦羔樅驼土靠梢赃M行加減
、谌魀1,p2為指針,當p1和p2指向同一類型時,可以進行賦值。
、蹆蓚指向同一類型的指針,可進行= =,>,<等關(guān)系運算,其實就是地址的比較。
、軆蓚指向同一數(shù)組成員的指針可進行相減,結(jié)果為兩個指針之間相差元素的個數(shù)。
注意:兩指針不能相加。
2指針和數(shù)組
在C+ +中,指針和數(shù)組的關(guān)系極為密切。實際上,數(shù)組的參數(shù)傳遞、數(shù)組元素的存取,都可通過指針操作來完成。指針和數(shù)組常?梢曰Q。
在C+ +中,數(shù)組的名字就是指向該數(shù)組第一個元素(下標為0)的指針,即該數(shù)組第一個元素的地址,也即數(shù)組的首地址。
一般情況下,一個數(shù)組元素的下標訪問a[i]等價于相應的指針訪問*(a+i)。但特別注意:數(shù)組名和指針(變量)是有區(qū)別的,前者是常量,即數(shù)組名是一個常量指針,而后者是指針變量。因此,盡管我們可寫pa=a;但不能寫:a=pa;或pa=&a;因為我們不能改變常量的值,也不能取常量的地址。
數(shù)組名可作為參數(shù)進行傳遞。當將數(shù)組名傳給函數(shù)時,實際上所傳遞的是數(shù)組的開始地址。(即數(shù)組第一個元素的地址)
為什么要使用指針?簡單地說指針運算比數(shù)組運算的速度快。
此外,使用指針的另外一個原因是在大量數(shù)據(jù)傳遞時,使用傳遞指針要遠比傳遞數(shù)據(jù)本身效率高的多,如在函數(shù)參數(shù)傳遞及函數(shù)返回值時。當然,使用指針會給程序帶來安全隱患(如指針懸掛問題),同時還使得程序的可讀性降低(顯然,用數(shù)組實現(xiàn)的程序要比用指針實現(xiàn)的程序的可讀性要好)。
對于字符串常量,可以把它看成是一個無名字符數(shù)組,C+ +編譯程序會自動為它分配一個空間來存放這個常量,字符串常量的值本身就是指向這個無名字符數(shù)組的第一個字符的指針,其類型是字符指針。
3指針數(shù)組和函數(shù)指針
(1)指針數(shù)組
指針數(shù)組就是由指針組成的數(shù)組,即數(shù)組中的每一個元素都是指向同一類型對象的指針。
指針數(shù)組可以是全局的、靜態(tài)的和局部的。字符指針數(shù)組和二維字符數(shù)組在許多方面是一樣的,如初始化形式、成員訪問方式,因此我們有必要了解它們的區(qū)別和各自的使用場合。
盡管二維字符數(shù)組與字符指針數(shù)組在存儲形式上不同,但它們在初始化形式以及訪問元素方式上卻是相同的。
采用指針數(shù)組的理由是:它可以節(jié)省存貯空間,因而通常用來存放不同長度的字符串。例如,如果要保存從標準輸入或文件中讀入的行,字符指針數(shù)組是一個好的選擇。因為讀入的行可能長短差異很大。
(2)命令行參數(shù)
在C+ +中可以實現(xiàn)帶有命令行參數(shù)的程序,它是通過main帶有參數(shù)來實現(xiàn)的。
在C+ +中,主函數(shù)main還可以帶有參數(shù),形式如下:
int main(int argc,char * argv[])
或int main(int argc,char * * argv[])
其中:
argc為包含命令本身在內(nèi)的參數(shù)個數(shù)。
argc為指針數(shù)組,數(shù)組元素為指向各參數(shù)(包含命令本身在內(nèi))的指針。
(3)函數(shù)指針
在C+ +中,允許指針指向一個函數(shù),即指向函數(shù)的指針。函數(shù)指針的說明形式為:
類型(*標識符)();
例如:int (* fp)();定義了一個指向返回值為整型值的函數(shù)的指針fp。
注意:int(*fp)();與int*fp();的不同在于,前者是函數(shù)指針,后者為返回指向int指針的函數(shù)。
與其他類型的指針變量一樣,在使用函數(shù)指針前必須使它指向一個具體的函數(shù)。若要函數(shù)指針指向一個具體函數(shù),可通過賦值語句或參數(shù)傳遞。
函數(shù)指針=函數(shù)名;
該賦值語句將使一個函數(shù)指針指向一個具體函數(shù)(在C+ +中,函數(shù)名是作為指向函數(shù)的指針值來處理)。函數(shù)指針的最大用途是它可以使得一個函數(shù)作為其他函數(shù)的參數(shù)進行傳遞,擴展了函數(shù)的功能。
4.3 引用
1引用的概念
引用是個別名,建立時須用另一個數(shù)據(jù)對象(如一個變量)的名字進行初始化,以指定該引用所代表的數(shù)據(jù)對象。此后,對引用的任何實操作實際上就是對所代表的數(shù)據(jù)對象的操作。一個引用變量要占用相當于一個指針所需要的空間,但系統(tǒng)不會為它所代表的數(shù)據(jù)對象再次分配空間。
在類型名后跟引用運算符“&”,以及引用名來創(chuàng)建一個引用。引用名就是一個變量名。
注意:引用運算符與地址操作符使用相同的符號(即運算符重載),但它們含義不一樣。引用運算符只在聲明變量的時候使用,它放在類型名后面。
使用引用時應遵循一定的規(guī)則:
(1)引用被創(chuàng)建時,它必須立即被初始化(指針則可以在任何時候被初始化)。
(2)一旦一個引用被初始化為一個對象的引用,它就不能再被改變?yōu)閷α硪粋對象的引用。(指針則可以在任何時候改變?yōu)橹赶蛄硪粋對象。)
(3)不可能有NULL引用。必須確保引用是具體合法的對象的引用(即引用應和一塊合法的存儲空間關(guān)聯(lián))。
2用引用傳遞函數(shù)參數(shù)
引用的一個重要用途就是作為函數(shù)的參數(shù)。在C+ +中,函數(shù)參數(shù)傳遞采用的是傳值,如果要有占用空間大的對象(例如一個大的結(jié)構(gòu)對象或類對象)需要作為函數(shù)參數(shù)傳遞的時候,在C語言中的做法往往是使用指針,因為這樣可以避免將整個實參對象數(shù)據(jù)全部拷貝給形式參數(shù),可以提高程序的執(zhí)行效率。在C+ +中,既可以使用指針,但由于C+ +引入了引用概念,亦可以用引用來做同樣的事情。引用作為參數(shù)的最大好處是:引用參數(shù)既可以像指針那樣工作,其使用方式又和一般變量相同。也就是說,引用比指針具有更好的可讀性。
4.4 動態(tài)存儲分配
動態(tài)存儲分配功能在C+ +中是通過new和delete運算符來實現(xiàn)的。
1使用new獲得動態(tài)內(nèi)存空間
運算符new用于申請動態(tài)存儲空間,它的操作數(shù)為某種數(shù)據(jù)類型且可以帶有初值表達式或元素個數(shù)。new返回一個指向其操作類型變量的指針。使用new對某種類型變量進行動態(tài)分配的語法格式為:
<指針>=new<類型>;
其中,<類型>表示要分配的變量類型(如char、int、double);<指針>表示指向<類型>類型變量的指針(如char*、int*、double*等)。
2使用delete釋放動態(tài)內(nèi)存空間
當動態(tài)分配的內(nèi)存空間在程序中使用完畢之后,必須顯式地將它們釋放。這樣做的目的是把閑置不用的堆內(nèi)存歸還給系統(tǒng),使其可以被系統(tǒng)重新分配。在C+ +程序中由new分配的動態(tài)內(nèi)存空間必須通過delete運算符釋放。使用delete對動態(tài)分配的單個變量進行釋放的語法格式為:
delete<指針>;
其中,<指針>表示指向單個變量的指針。
使用delete對動態(tài)分配的數(shù)組進行釋放的語法格式為:
delete[]<指針>;
其中,<指針>表示指向數(shù)組首元素的指針。delete之后的方括號指明將要釋放的內(nèi)存空間中存儲著數(shù)組元素。程序中需要分配動態(tài)內(nèi)存空間,則new和delete總是成對出現(xiàn)的。
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |