《C Primer 5e》學習筆記(5) 函式

2021-07-09 07:58:21 字數 4436 閱讀 6286

1.函式的呼叫完成兩項工作:一是用實參初始化函式對應的形參,二是將控制權轉移給被呼叫的函式。此時,主調函式的執行被暫時中斷,被調函式開始執行。

2.函式定義規定了實參與形參存在的對應關係,但是並沒有規定實參的求值順序。編譯器能以任意可行的順序對形參進行求值。

3.函式的返回值不能是陣列型別或函式型別,但可以是指向陣列或函式的指標。

4.區域性靜態物件在程式執行路徑第一次經過物件定義語句時初始化,並且直到程式終止才被銷毀,在此期間即使物件所在的函式結束執行也不會對它有影響。

#include using namespace std;

size_t count_calls()

int main()

9.const形參和實參:(頂層const作用於物件本身)和其他初始化過程一樣,當用實參初始化形參時會忽略掉頂層const。換句話說,形參的頂層const被忽略掉了。當形參有頂層const時,傳給它常量或非常量都是可以的:

void fcn(const int i) //fcn能夠讀取i,但不能向i寫值

void fcn(int i) //錯誤,重複定義了fcn

另一方面,如果形參是某種型別的指標或者引用,則通過區分其指向的是常量物件還是非常量物件可以實現函式過載,此時的const的底層的:

void loopup(account&); //函式作用於account的引用

void loopup(const account&); //新函式,函式作用於常量引用

10.我們可以使用非常量初始化乙個底層const,但是反過來不行;同時乙個普通的引用必須用同型別的物件初始化。

#include using namespace std;

void reset(int *ip)

void reset(int &i)

int main()

要想呼叫引用版本的reset,只能用int型別的物件,而不能使用字面值、求值結果為int的表示式、需要轉換的物件或者const int的物件。類似的,想要呼叫指標版本的reset只能用int*。

11.陣列的引用:(注意引用運算子的優先順序低於下標運算子)

#include using namespace std;

//void exa(int &a[5]) //將a宣告成了引用的陣列:編譯錯誤

void exa(int (&a)[5]) //對具有5個整數的整型陣列的引用

int main()

; exa(a);

for(int i=0;i<5;i++)

cout<

12.

int main(int argc,char *argv) //........(1)

int main(int argc,char **argv) //........(2)

式(1)中第二個形參argv是乙個陣列,它的元素是指向c風格字串的指標;第乙個引數argv表示陣列中字串的數量。由於第二個形參是陣列,所以main函式也可以定義

成式(2)這樣。

當實參傳遞給main函式之後,argv的第乙個元素指向程式的名字或者乙個空字串,接下來的元素以此傳遞給命令列提供的實參,最後乙個指標的元素保證為0(即空字串)。

13.return語句終止當前正在執行的函式並將控制權返回到呼叫該函式的地方。返回乙個值的方式和初始化變數或形參的方式完全一樣:返回的值用於初始化呼叫點的乙個臨時量,該臨時量就是函式呼叫的結果。函式返回的結果(即函式的返回值)將被拷貝到呼叫點。如果函式返回引用,則該引用僅是它所引物件的乙個別名:

const string& shorter_string(const string &s1,const string &s2)

其中形參和返回型別都是const string的引用,不管是呼叫函式還是返回結果都不會真正拷貝string物件。

14.函式完成後,它所佔的儲存空間也隨之被釋放掉,因此,函式終止意味著區域性變數的引用將指向不再有效區的記憶體區域。

15.函式的返回型別決定函式呼叫是否為左值。呼叫乙個返回引用的函式得到左值,其他返回型別得到右值。

16.c++11新標準規定,函式可以返回花括號包圍的值的列表:

vectorprocess()

; //返回乙個空vector物件

else if(expected==actual)

return ; //返回列表初始化的vector物件

else return ;

}

17.因為陣列不能被拷貝,所以函式不能返回陣列。不過,函式可以返回陣列的指標或引用:

typedef int arr[10]; //arr是乙個型別別名,表示的型別是含有10個整數的陣列

using arr=int[10]; //arr的等價宣告

arr* func(int i); //func返回乙個指向含有10個整數的陣列的指標

//如果不用型別別名,我們必須牢記被定義的名字後面陣列的維度

int arr[10]; //arr是乙個含有10個整數的陣列

int *p1[10]; //p1是乙個含有10個指標的陣列

int (*p2)[10]=&arr; //p2是乙個指標,指向含有10個整數的陣列

和這些宣告一樣,如果我們定義乙個返回陣列指標的函式,則陣列的維度必須跟在函式名字之後:

int (*func(int i))[10]; //如果沒有最外面的括號,函式的返回型別將是指標的陣列

18.c++中,名字查詢發生在型別檢查之前

string read();

void print(const string&);

void print(double); //過載print函式

void example(int ival)

當我們呼叫print函式時,編譯器首先尋找對函式的宣告,一旦在當前作用域找到了所需的名字,編譯器就會忽略掉外層作用域的名字,剩下的工作就是檢查函式呼叫是否有效了。

19.呼叫含有預設實參的函式

string func(int a=24,int b=45,char bk=' ');

string tmp;

tmp=func(); //等價於func(24,45,' ')

tmp=func(66); //等價於func(66,45,' ')

用作預設實參的名字在函式宣告所在的作用域內解析,而這些名字的求值過程發生在函式呼叫時。

20.函式指標指向的函式而非物件。和其他指標一樣,函式指標指向某種型別,其型別由它的返回型別和形參型別共同決定。

//比較兩個string物件的長度

bool length_compare(const string&,const string&);

該函式的型別是bool(const string&,const string&),想要宣告乙個可以指向該函式的指標,只需用指標替換函式名即可:

//pf指向乙個函式,該函式的引數是兩個const string的引用,返回值是bool型別

bool (*pf)(const string&,const string&);

21.使用函式指標:

當我們把函式名作為乙個值使用時,該函式自動地轉換成指標:

pf=length_compare; //pf指向名為length_compare的函式

pf=&length_compare; //等價的賦值語句:取位址符是可選的

此外,我們還能直接使用指向函式的指標呼叫該函式,無須提前解引用指標:

bool p1=pf("hello","goodbye"); //呼叫length_compare函式

bool p2=(*pf)("hello","goodbye"); //乙個等價的呼叫

bool p3=length_compare("hello","goodbye"); //另乙個等價呼叫

c primer, 5e 函式指標

簡單的示例 include using namespace std int sum int x,int y int main 遇到過載的情況,編譯器通過指標型別精確匹配函式。include using namespace std int sum int x,int y int sum int x,d...

c primer, 5e 函式匹配

練習 6.49 候選函式 與所呼叫的函式的名字相同的函式的集合。可行函式 給候選函式加上引數數量 引數型別的約束所得到的函式的集合。6.50 a 3 4可行,二義匹配 b 2 4可行,2是最佳匹配 c 3 4可行,3是最佳匹配 d 3 4可行,4是最佳匹配 6.51 測試 include using...

C Primer(5e)第13章習題

如果乙個建構函式的第乙個引數是自身類型別的引用,且任何額外引數都有預設值,則此建構函式是拷貝建構函式。使用時候 1.用 定義變數 2.將要給物件作為實參傳遞給乙個非引用型別的實參 3.從乙個返回型別為非引用型別的函式返回乙個物件 4.用花括號列表初始化乙個陣列中的元素或乙個聚合類中的成員 因為如果拷...