CPP_Basic_Summary_0.7
1、C++要求函數(shù)的返回值不能是數(shù)組,但可以將數(shù)組作為結(jié)構(gòu)或?qū)ο蠼M成部分來(lái)返回
2、C++的編程風(fēng)格因?yàn)楹瘮?shù)原型必須存在,所以提倡main()置于最前面
3、函數(shù)原型不要求必須提供變量名,只需要類型列表就可以:
void test(double ar[],int);
void test(double [],int);
void test(double*,int);//三者同義
4、通常如果可能且僅當(dāng)有意義時(shí),原型自動(dòng)將被傳遞的參數(shù)強(qiáng)制轉(zhuǎn)換為期望的類型
5、在編譯階段進(jìn)行的原型化被稱為靜態(tài)類型檢查,這種檢查可以捕獲很多運(yùn)行階段難以捕獲的錯(cuò)誤
6、函數(shù)的內(nèi)部變量(包括參數(shù))是局部變量,函數(shù)結(jié)束將釋放這些內(nèi)存,按值傳遞時(shí)函數(shù)形參傳遞的是副本
7、在進(jìn)行諸如階乘這類大規(guī)模計(jì)算的時(shí)候,采用交替進(jìn)行乘除運(yùn)算的方式,可以有效防止中間結(jié)果超最大值而溢出
8、數(shù)組名在大部分時(shí)候等同于指向第一個(gè)元素的指針,但有以下情形除外:首先是數(shù)組聲明用數(shù)組名來(lái)標(biāo)記存儲(chǔ)位置;其次,對(duì)數(shù)組名使用sizeof將得到整個(gè)數(shù)組的長(zhǎng)度(字節(jié)為單位);然后是將地址運(yùn)算符&用于數(shù)組名時(shí),將返回整個(gè)數(shù)組的地址
9、將指針(包括數(shù)組名)+1,實(shí)際上是加上了一個(gè)與指針指向類型的長(zhǎng)度(字節(jié)為單位)相等的值
10、函數(shù)調(diào)用數(shù)組必須通過(guò)數(shù)組名,也就是指針傳遞的方式,可以用數(shù)組名和數(shù)組容量搭配的方式:
void demo(double arr[],int size);
也能使用兩個(gè)指針來(lái)指出數(shù)組的開(kāi)頭位置和結(jié)尾位置:
int sum_arr(cookies,cookies+size);
11、const double ar[]:保護(hù)指針指向的內(nèi)容不被修改;但只意味著對(duì)于ar來(lái)說(shuō)不可以更改,別的指針或許可以,且指針ar本身也可以被修改
12、int* const pt=&age:意味著指針本身不可被修改。簡(jiǎn)而言之:前置const鎖數(shù)據(jù),后置const鎖指針,同時(shí)則都鎖。需要非常注意的是,如果數(shù)組元素不是基本類型,而是指針或者指向指針的指針,則不能使用const(比如2D數(shù)組)
13、C++禁止將const的地址賦給非const指針,若數(shù)據(jù)類型本身不是指針,則可以將const數(shù)據(jù)或非const數(shù)據(jù)的地址賦給指向const的指針,但是只能將非const數(shù)據(jù)的地址賦給非const指針
14、2D數(shù)組的函數(shù)定義:int sum(int ar2[] [4],int size);可見(jiàn)是單獨(dú)傳遞行數(shù)的。ar2[r][c]==*(*(ar2+r)+c)兩者完全等價(jià)
15、const char* str="name";即可聲明指向字符串的指針str,此處const對(duì)于C++11標(biāo)準(zhǔn)是必須的
16、處理字符串中字符的標(biāo)準(zhǔn)方式:
while (*str)
{
statements;
str++;
}
此循環(huán)每次增加使得str指向下一個(gè)字符,直到最后的'\0'將使*str==0(空值字符的數(shù)字編碼),從而中斷循環(huán)
17、從后向前的循環(huán)一般可以節(jié)省額外的變量i,比如:
while (n-- >0)
{
pstr[n]=c;
}
18、子函數(shù)結(jié)束時(shí),所有局部變量都會(huì)被釋放,即返回的指針的內(nèi)存會(huì)被釋放,但是其值會(huì)被返回到main()中,故仍可以通過(guò)main()中的指針對(duì)新建的字符串相關(guān)內(nèi)容進(jìn)行訪問(wèn)
19、函數(shù)中使用結(jié)構(gòu)可以使用實(shí)值直接傳遞和結(jié)構(gòu)指針兩種方式,但是出于效率考慮,應(yīng)該優(yōu)先使用指針。除此以外,還有引用的方式可以解決 表示和效率 兩方面的問(wèn)題
20、函數(shù)中使用string對(duì)象數(shù)組:
string list[size];
getline(cin,list[i]);
21、函數(shù)中使用array對(duì)象,除了基本數(shù)據(jù)類型,array還可以存儲(chǔ)類對(duì)象:
array<double,4> expenses;
const array<string,4> sname {"Spring","Summer","Fall","Winter"};
void show(array<double,4> da);
void fill(array<double,4> *pa);
show(expenses);
fill(&expenses);
22、遞歸(也稱 分而治之):C++允許遞歸調(diào)用除了main()以外的子函數(shù):
void recurs(argumentlist)
{
statements1;
if (test)//test最終為false將跳出循環(huán)
recurs(arguments);//此處的遞歸調(diào)用應(yīng)該更新test條件
statements2;
}//若statements1將按照調(diào)用順序執(zhí)行n次,則statements2將按照與函數(shù)調(diào)用相反的順序執(zhí)行n次
23、每一套遞歸調(diào)用都創(chuàng)建自己的一套變量,因此若程序達(dá)到第5次調(diào)用的時(shí)候,將有5個(gè)獨(dú)立的變量:
void countdown(int n)
{
if (n>0)
countdown(n-1);
}
24、函數(shù)的地址是存儲(chǔ)其機(jī)器語(yǔ)言代碼的內(nèi)存的開(kāi)始地址。函數(shù)指針允許在不同的時(shí)間傳遞不同函數(shù)的地址,這意味著可以在不同的時(shí)間使用不同的函數(shù)。函數(shù)的地址就是函數(shù)名,需要注意的是區(qū)分函數(shù)本身和函數(shù)的返回值:
process(think);//傳遞的是函數(shù)的地址
thought(think());//傳遞的是函數(shù)的返回值
25、聲明一個(gè)函數(shù)指針,通??梢韵葘懗龊瘮?shù)的原型,然后用諸如(*pf)這樣的函數(shù)指針替換函數(shù)名即可:
double (*pf)(int);//pf是指向函數(shù)的指針,該函數(shù)返回值類型為double,形參為int
double* pf(int);//pf是一個(gè)函數(shù),接受int形參,且返回值的類型為double*指針
26、需要注意C++特別規(guī)定,若pf是一個(gè)函數(shù)指針,則:
double y=(*pf)(5)和double y=pf(5)是完全等價(jià)的,也即此處(*pf)==pf。為強(qiáng)調(diào)是函數(shù)指針,建議使用前者
27、類似地,以下代碼含義完全一致:
cout<<(*p1)(av,3)<<*(*p1)(av,3)<<endl;
//第一部分是函數(shù)調(diào)用,返回double*指針,第二部分再次解除*,獲得具體的double實(shí)值
cout<<p2(av,3)<<*p2(av,3)<<endl;
//同理,第一部分函數(shù)調(diào)用,返回double*指針,第二部分是具體的double實(shí)值
28、創(chuàng)建指向整個(gè)函數(shù)指針數(shù)組的指針:
const double* (*(*pd)[3]) (const double*,int)=&pa
//*pd表明pd是指針,右側(cè)[3]說(shuō)明指針指向一個(gè)數(shù)組
//*(*pd)最左側(cè)的*表明數(shù)組的元素是指針
//觀察左右兩側(cè)發(fā)現(xiàn)數(shù)組的元素是函數(shù)指針
//左側(cè)const double*是返回值類型,右側(cè) (const double*,int)是形參
29、typedef用法:
例1:
typedef const double* (*p_fun) (const double*,int);
p_fun p1=f1;
p_fun pa[3] {f1,f2,f3};
p_fun (*pd) [3]=&pa;
例2:
void (*p1)(形參)=f1;
const char* (*p2)(形參)=f2;
void (*ap[5])(形參);
const char* (*(*pa)[10])(形參);
//可簡(jiǎn)化為:
typedef void (*p_f1)(形參);
p_f1 p1=f1;
typedef const char* (*p_f2)(形參);
p_f2 p2=f2;
p_f1 ap[5];
p_f2 (*pa)[10];
30、指針數(shù)組 數(shù)組指針 指針函數(shù) 函數(shù)指針
int *p[4]; //指針數(shù)組
//它是個(gè)有4個(gè)元素的數(shù)組, 每個(gè)元素的是指向整型的指針。(數(shù)組的每個(gè)元素都是指針)
int (*p)[4]; //數(shù)組指針。
//它是一個(gè)指針,指向有4個(gè)整型元素的數(shù)組。(一個(gè)指針指向有4個(gè)整型元素的數(shù)組)
int *func(void); //指針函數(shù)。
//無(wú)參函數(shù), 返回整型指針。(函數(shù)的返回值為int*)
int (*func)(void);//函數(shù)指針
//可以指向無(wú)參, 且返回值為整型指針的函數(shù)。(函數(shù)的返回值為int)
31、復(fù)雜函數(shù)指針閱讀說(shuō)明:
右左法則其實(shí)并不是C++標(biāo)準(zhǔn)里面的內(nèi)容,它是從C++標(biāo)準(zhǔn)的聲明規(guī)定中歸納出來(lái)的方法。C++標(biāo)準(zhǔn)的聲明規(guī)則,是用來(lái)解決如何創(chuàng)建聲明的,而右左法則是用來(lái)解決如何辯識(shí)一個(gè)聲明的,兩者可以說(shuō)是相反的。
右左法則:首先從最里面的圓括號(hào)(未定義的標(biāo)識(shí)符)看起,然后往右看,再往左看。每當(dāng)遇到圓括號(hào)時(shí),就應(yīng)該掉轉(zhuǎn)閱讀方向。一旦解析完圓括號(hào)里面所有的東西,就跳出圓括號(hào)。重復(fù)這個(gè)過(guò)程直到整個(gè)聲明解析完畢。
對(duì)這個(gè)法則應(yīng)該進(jìn)行一個(gè)小小的修正,應(yīng)該從未定義的標(biāo)識(shí)符開(kāi)始閱讀,而不是從括號(hào)讀起,之所以是未定義的標(biāo)識(shí)符,是因?yàn)橐粋€(gè)聲明里面可能有多個(gè)標(biāo)識(shí)符,但未定義的標(biāo)識(shí)符只會(huì)有一個(gè)。
現(xiàn)在通過(guò)一些例子來(lái)討論右左法則:
int (*func)(int *p);
首先找到那個(gè)未定義的標(biāo)識(shí)符,就是func,它的外面有一對(duì)圓括號(hào),而且左邊是一個(gè)號(hào),這說(shuō)明func是一個(gè)指針,
然后跳出這個(gè)圓括號(hào),先看右邊,也是一個(gè)圓括號(hào),這說(shuō)明(func)是一個(gè)函數(shù),而func是一個(gè)指向這類函數(shù)的指針,就是一個(gè)函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值類型是 int。
int (*func)(int *p, int (*f)(int*));
func被一對(duì)括號(hào)包含,且左邊有一個(gè)號(hào),說(shuō)明func是一個(gè)指針,跳出括號(hào),右邊也有個(gè)括號(hào),那么func是一個(gè)指向函數(shù)的指針,這類函數(shù)具有int 和int ()(int)這樣的形參,返回值為int類型。再來(lái)看一看func的形參int (f)(int),類似前面的解釋,f也是一個(gè)函數(shù)指針,指向的函數(shù)具有int*類型的形參,返回值為int。
int (*func[5])(int *p);
func右邊是一個(gè)[]運(yùn)算符,說(shuō)明func是一個(gè)具有5個(gè)元素的數(shù)組,func的左邊有一個(gè),說(shuō)明func的元素是指針,要注意這里的不是修飾 func的,而是修飾func[5]的,原因是[]運(yùn)算符優(yōu)先級(jí)比高,func先跟[]結(jié)合,因此修飾的是func[5]。跳出這個(gè)括號(hào),看右邊,也是一對(duì)圓括號(hào),說(shuō)明func數(shù)組的元素是函數(shù)類型的指針,它所指向的函數(shù)具有int*類型的形參,返回值類型為int。
int (*(*func)[5])(int *p);
func被一個(gè)圓括號(hào)包含,左邊又有一個(gè),那么func是一個(gè)指針,跳出括號(hào),右邊是一個(gè)[]運(yùn)算符號(hào),說(shuō)明func是一個(gè)指向數(shù)組的指針,現(xiàn)在往左看,左邊有一個(gè)號(hào),說(shuō)明這個(gè)數(shù)組的元素是指針,再跳出括號(hào),右邊又有一個(gè)括號(hào),說(shuō)明這個(gè)數(shù)組的元素是指向函數(shù)的指針??偨Y(jié)一下,就是:func是一個(gè)指向數(shù)組的指針,這個(gè)數(shù)組的元素是函數(shù)指針,這些指針指向具有int*形參,返回值為int類型的函數(shù)。
int (*(*func)(int *p))[5];
func是一個(gè)函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值是指向數(shù)組的指針,所指向的數(shù)組的元素是具有5個(gè)int元素的數(shù)組。
32、要注意有些復(fù)雜指針聲明是非法的,例如:
int func(void) [5];
func是一個(gè)返回值為具有5個(gè)int元素的數(shù)組的函數(shù)。但C語(yǔ)言的函數(shù)返回值不能為數(shù)組,這是因?yàn)槿绻试S函數(shù)返回值為數(shù)組,
那么接收這個(gè)數(shù)組的內(nèi)容的東西,也必須是一個(gè)數(shù)組,但C語(yǔ)言
的數(shù)組名是一個(gè)右值,它不能作為左值來(lái)接收另一個(gè)數(shù)組,因此函數(shù)返回值不能為數(shù)組。
int func[5](void);
func是一個(gè)具有5個(gè)元素的數(shù)組,這個(gè)數(shù)組的元素都是函數(shù)。這也是非法的,因?yàn)閿?shù)組的元素除了類型必須一樣外,每個(gè)元素所占用的內(nèi)存空間也必須相同,顯然函數(shù)是無(wú)法達(dá)到這個(gè)要求的,即使函數(shù)的類型一樣,但函數(shù)所占用的空間通常是不相同的。實(shí)際當(dāng)中,需要聲明一個(gè)復(fù)雜指針時(shí),如果把整個(gè)聲明寫成上面所示的形式,對(duì)程序可讀性是一大損害。應(yīng)該用typedef來(lái)對(duì)聲明逐層分解,增強(qiáng)可讀性。
33、用typedef的分解方法:
int (*(*func)[5][6])[7][8];
func是一個(gè)指向數(shù)組的指針,這類數(shù)組的元素是一個(gè)具有5X6個(gè)int元素的二維數(shù)組,而這個(gè)二維數(shù)組的元素又是一個(gè)二維數(shù)組。
typedef int (*PARA)[7][8];
typedef PARA (*func)[5][6];
int (*(*(*func)(int *))[5])(int *);
func是一個(gè)函數(shù)指針,這類函數(shù)的返回值是一個(gè)指向數(shù)組的指針,所指向數(shù)組的元素也是函數(shù)指針,指向的函數(shù)具有int*形參,返回值為int。
typedef int (*PARA1)(int*);
typedef PARA1 (*PARA2)[5];
typedef PARA2 (*func)(int*);
int (*(*func[7][8][9])(int*))[5];
func是一個(gè)數(shù)組,這個(gè)數(shù)組的元素是函數(shù)指針,這類函數(shù)具有int*的形參,返回值是指向數(shù)組的指針,所指向的數(shù)組的元素是具有5個(gè)int元素的數(shù)組。
typedef int (*PARA1)[5];
typedef PARA1 (*PARA2)(int*);
typedef PARA2 func[7][8][9];