Essential C 學習(二)面向過程程式設計

2021-10-02 13:25:05 字數 4582 閱讀 6183

函式包含函式名,返回型別,引數列表和函式體,必須先宣告才能被呼叫。

練習2.1 使用者詢問fibonacci數列的任一位置的元素值,輸出並列印數列。

#include #include#includeusing namespace std;

bool fibon_elem(int, int&);

bool fibon_elem(int pos, int&elem)

//第乙個和第二個數都是1 elem=1

elem = 1;

int n1 = 1;

int n2 = 1;

for (int ix = 2; ix < pos; ++ix)

return true;

}bool print_sequence(int pos)

cout << "the fibonacci sequence for " << pos << " positions: \n\t"<> pos;

int elem;

if (fibon_elem(pos, elem))

else cout << "wtf" << endl;

} system("pause");

return 0;

}

當我們呼叫乙個函式時,會在記憶體中建立一塊特殊區域,稱為程式堆疊」program stack「。堆疊提供了每個函式引數的儲存空間,也提供了函式所定義的每個物件的記憶體空間,這些物件被稱為local object(區域性物件)。一旦函式完成,這塊記憶體會被釋放掉,也就是pop出來。

要將函式的引數和傳入的實際物件產生關聯,即」傳址「,需要將引數宣告為乙個reference。不就是形參和實參?

函式引數的傳遞應該採用傳址方式而非傳值方式。

void swap(int val1, int val2);

void swap(int &val1, int &val2);

宣告乙個reference:

int ival=1024;

int *pi=&ival;

int &rval=ival;

//將jval賦值給ival

int jval=4096;

rval=jval;

//將ival的位址賦值給pi

pi=&rval;

面對reference的所有操作都和面對」reference所代表的物件「所進行的操作一樣。傳址主要用於全域性物件class object而非區域性物件local object。reference和pointer的效果是相同的,不一樣的是使用方式,而且pointer有可能為空指標,使用前要先檢查pointer的值非0。

reference:

const vector&vec

vec.size()

vec[ix]

pointer:

const vector*vec

vec->size()

(*vec)[ix]

程式的的heap memory(堆記憶體)分配使用new,釋放通過delete。

int *pi = new int(1024);//從heap分配物件可初始化也可不指定初值

int *pia =new int[24];//從heap分配陣列無法為元素設定初值

delete pi;

delete pia;//要加乙個空的下標運算子

從heap分配來的物件除非被delete掉否則永遠不會被釋放,這叫做memory leak(記憶體洩露)。

可為函式的部分或全部引數設定預設值,兩個規則:

1. 為某個引數提供了預設值,那麼這一引數右側的所有引數都必須也具有預設引數值;

2. 預設值只能宣告一次,可以將預設值放在函式宣告處放在標頭檔案.h裡。

區域性靜態物件(local static object)所處記憶體空間,即使在不同的函式呼叫過程中,依然持續存在。

關鍵字inline 必須與函式定義體放在一起才能使函式成為內聯,僅將inline 放在函式宣告前面不起任何作用。

使用情況:使用多個函式,執行效果不理想。將函式宣告為inline,表示要求編譯器在每個函式呼叫點上,將函式的內容展開。面對乙個inline函式,編譯器可將該函式的呼叫操作改為以乙份函式**副本代替。這將使我們獲得效能改善。為什麼呢?

慎用內聯

內聯是以**膨脹(複製)為代價,僅僅省去了函式呼叫的開銷,從而提高函式的執行效率。如果執行函式體內**的時間,相比於函式呼叫的開銷較大,那麼效率的收穫會很少。另一方面,每一處內聯函式的呼叫都要複製**,將使程式的總**量增大,消耗更多的記憶體空間。

適合被宣告為inline的函式:體積小,常被呼叫,所從事的計算不複雜。

inline函式的定義常被放在標頭檔案中。

function overloading:引數列表不相同的兩個或者多個函式可以擁有相同的函式名稱。可以將一組實現**不同但是工作內容相似的函式加以過載,呼叫時根據呼叫者提供的實際引數來區分函式。

void display_message(char ch);

void display_message(const string&);

void display_message(const string&, int);

function template(函式模板):將單一函式的內容與希望顯示的各種vector型別繫結(bind)起來,將引數列表中指定的全部(或部分)引數的型別資訊抽離了出來。

以關鍵字template開場,緊接以<>包圍起來的乙個或多個識別符號。使用者每次利用模板產生函式都必須提供確實的型別資訊。

templatevoid display(const string string &msg, const vector&vec){}
elemtype在display_message()函式中是乙個暫時放置型別的佔位符,可以被繫結為內建型別或使用者自定義型別。

vectorivec;

string msg;

//...

display_message(msg,ivec);

編譯器會將elemtype繫結為int型別,然後產生乙份display_message()函式例項,於是第二引數的型別即變成vector。

function template同時也可以function overload。下面乙個的第二引數型別為vector,另乙個的第二引數型別為list。

templatevoid display_message(const string &msg, const vector&vec);

templatevoid display_message(const string &msg, const list<);

必須指明其所指函式的返回型別及引數列表

必須將 * 放在某個位置

必須給予乙個名稱

const vector* (*seq_ptr) (int);
seq_ptr被定義為乙個指標,指向返回型別為const vector*和引數列表為int的任何乙個函式。

和一般函式相同。

const vector* pseq = seq_ptr(pos);
會間接呼叫seq_ptr所指向的函式。如果函式指標的初值為0,表示並未指向任何函式。

const vector* (*seq_ptr) (int) = 0;
//seq_array是個陣列,內放函式指標

const vector* (*seq_array)(int)=;

關鍵字enum。預設情形下,第乙個列舉項的值為0,接下來每個列舉項都多1。可以作為陣列索引值。

enum ns_type;
函式的定義只能有乙份,不過可以有許多份宣告,函式的宣告都放在標頭檔案裡,inline函式除外。

在file scope(全域性範圍)內定義的物件,如果可能被多個檔案訪問,就應被宣告於標頭檔案中。

在seq_array的定義前加關鍵字extern使它成為乙個宣告。

const int seq_cnt = 6;

extern const vector* (*seq_array[seq_cnt])(int);

為什麼在seq_cnt前不加extern?

const object的定義只要一出檔案之外便不可見,可以在多個程式**檔案中加以定義,不會導致任何錯誤。因為我們希望編譯器在陣列宣告中使用這一const object,並且在其他需要用到常量表示式的場合中(可能跨檔案)也能使用。

任何需要用到seq_array的檔案都要包含對應標頭檔案。

#include "numseq.h"
使用雙引號「」而不是<>的原因:""包住的標頭檔案被認為是使用者提供的,搜尋時編譯器先從包含此檔案的檔案所在磁碟目錄找起;<>包住的標頭檔案被認為是標準的或者專案專屬的,編譯器會先在某些預設的磁碟目錄找起。

Essential C 之面向過程

include using namespace std bool fibon elem int int int main bool fibon elem int pos,int elem 位置值為1和2時,elem的值為1 elem 1 int n 2 1 int n 1 1 for int ix ...

Essential C 學習筆記

essential c 學習筆記 系統學習c 的第一天,做點小筆記。使用c 進行檔案讀寫操作的例程 寫檔案 include include using namespace std 一定要新增這句 使用標準的命名 intmain 讀檔案 讀檔案的操作 include include include u...

Essential C 學習筆記 五

5.1 物件導向程式設計概念 1.物件導向風格的三個獨特概念 繼承 inheritance 多型 polymorphism 動態繫結 dynamic binding 2.多型和動態繫結的特性,只有在使用pointer或reference時才能發揮.5.2 物件導向程式設計思維 1.當程式定義出乙個派...