《c++ primer plus》第7章知識點總結
簡單的知識不再進行贅述
形參:函式頭中用於接受傳遞值的變數
實參:傳遞給函式的值
使用c++函式,必須完成以下工作:
(1)提供函式定義
(2)提供函式原型
(3)呼叫函式
函式原型
當函式沒有寫在main函式前面,而是寫在後面時,需要在main前面加上函式的原型,例如下面這個例子
#include void cheers(int);//這就是原型
double cube(double x);//這就是原型
int main()
void cheers(int n)
; int sum=sum_arr(cookies,arsize);
cout<
這是乙個最簡單的例子
函式如何使用指標來處理陣列
首先,在大多數情況下,c++和c語言一樣,也將陣列名視為指標。c++將陣列名解釋為其第乙個元素的位址
cookies==&cookies[0]
當然,該規則有一些例外:
(1)陣列宣告使用陣列名來標記儲存位置
(2)對陣列名使用sizeof將得到整個陣列的長度(以位元組為單位),比如sizeof cookies的值為32,而sizeof arr的值為4。因為sizeof arr只是指標變數的長度
(3)將位址運算子&用於陣列名時,將返回整個陣列的位址
在上面的例子中,執行了下面的函式呼叫
int sum_arr(cookies,arsize);
其中cookies是陣列名,而根據c++規則,cookies是其第乙個元素的位址,因此函式傳遞的是位址。由於陣列的元素的型別為int,因此cookies的型別必須是int指標,即int*。這表明,正確的函式頭應該是:
int sum_arr(int * arr,int n)
其中,int * arr替換了int arr。這證明兩個函式頭都是正確的,因為在c++中,當且僅當用於函式頭或函式原型中,int *arr和int arr的含義才是相同的。它們都意味著arr是乙個int指標。然而,陣列表示法(int arr)提醒使用者,arr不僅指向int,還指向int陣列的第乙個int。
就目前而言,要牢記以下兩個恒等式:
arr[i]==*(ar+i)
&arr[i]==ar+i
將指標(包括陣列名)加1,實際上是加上了乙個與指標指向的型別的長度(以位元組為單位)相等的值。對於便利陣列而言,使用指標加法和陣列下標時等效的。
為將陣列型別和元素數量告訴陣列處理函式,請通過兩個不同的引數來傳遞他們
void fillarray(int arr,int size);
而不要試圖使用方括號表示法來傳遞陣列長度
void fillarray(int arr[size]);——這是錯誤的
指標和const
為防止函式無意中修改陣列的內容,可在宣告形參時使用關鍵字const
void show_array(const double ar,int n);
該宣告表明,指標ar指向的是常量資料。這意味著不能使用ar修改該資料,也就是說可以使用像ar[0]這樣的值,但不能修改
我們可以用兩種不同的方式將const關鍵字用於指標
第一種方法是讓指標指向乙個常量物件,這樣可以防止使用該指標來修改所指向的值
第二種方法時將只做了本身宣告為常量,這樣可以放置改變指標指向的位置
下面來看幾個例子
int age=39;
const int *pt=&age;
//該宣告指出,pt指向乙個const int(這裡為39),因此不能使用pt來修改這個值
*pt+=1;
cin>>*pt;//這兩語句都不合法,因為不能使用pt來修改它所指向的值
*pt=20;
age=20;
//pt指向age,pt是const的,而age不是,因此不可以通過pt修改age的值但是可以直接通過age變數來修改age的值
const float g_earth=9.80;
const float *pe=&g_earth;
//這種情況下,既不能使用g_earth來修改值9.80,也不能使用pe來修改
const float g_moon=1.63;
float *pm=&g_moon;
//這種情況在c++中是非法的,因為如果將g_moon的位址賦給pm,
//則可以使用pm來修改g_moon,這使得g_moon的const狀態變得無效
int age=39;
const int *pt=&age;
//第二個宣告中const只能防止修改pt指向的值(這裡為39),而不能防止修改pt的值。
//也就是說可以將乙個新位址賦給pt,如下
int sage=80;
pt=&sage;
//此時pt指向位址的值為80,但仍然不能使用pt來修改指標的值
int sloth=3;
const int *ps=&sloth;
int *const finger=&sloth;
//這裡仔細觀察第二和第三個宣告中關鍵字const位置的不同
//第二個宣告中,不允許使用ps來修改sloth的值,但允許將ps指向另乙個位置
//第三個宣告中,finger只能指向sloth,但允許使用finger來修改sloth的值
//簡而言之,finger和*ps都是const,而*finger和ps不是
函式和二維陣列
假設存在下面的**
int data[3][4]=,,};
int total=sum(data,3);
那麼sum()的原型是:int sum(int (*ar2)[4],int size);
因為data是乙個陣列名,該陣列有3個元素。第乙個元素本身是乙個陣列,有4個int值組成。因此data的型別是指向由4個int組成的陣列的指標。下面這是另一種格式,含義一樣,但可讀性更強
int sum(int ar2[4],int size);
由於指標型別指定了列數,因此sum()函式只能接受由4列組成的陣列。但長度變數指定了行數,因此sum()對陣列的函式沒有限制
函式和c風格字串
表示字串的三種方式:
(1)char陣列
(2)用引號括起來的字串常量(也稱字串字面值)
(3)被設定為字串的位址的char指標
將字串作為引數來傳遞,實際傳遞的是字串第乙個字元的位址。這意味著字串函式原型應將其表示字串的形參宣告為char*型別。
c風格字串與常規char陣列之間的乙個重要區別是,字串有內建的結束字元(包含字元,但不以空值字元結尾的char陣列只是陣列,不是字串)
下面這裡個例子演示如何返回c風格字串的函式
#include const int arsize=8;
char *buildstr(char c,int n);
int main()
函式和結構
傳遞結構的位址而不是整個結構可以節省時間和空間。傳遞結構的位址時,由於形參是指標而不是結構,因此應間接成員運算子(->)而不是成員運算子(句點)。另外,做修改時不用返回乙個結構體,可以直接對位址上的資料進行修改
函式指標
與資料項相似,函式也有位址。函式的位址是儲存其機器語言**的記憶體的開始位址
獲取函式的位址
只要使用函式名即可,也就是說,如果think()是乙個函式,則think就是這個函式的位址
宣告函式指標
宣告指向某種資料型別的指標時,必須指定指標指向的型別。同樣,宣告指向函式的指標時,也必須指定指標指向的函式型別。這意味著宣告應指定函式的返回型別以及函式的特徵標(引數列表)。也就是說,宣告應像函式原型那樣指出有關函式的資訊。例如,乙個估算時間的函式原型如下:
double pam(int);
則正確的指標型別宣告如下:
double (*pf)(int);
這與pam()宣告類似,這是將pam替換為了(*pf)。由於pam是函式,因此(*pf)也是函式,pf就是函式指標
使用指標來呼叫函式
只需要把(*pf)看作函式名即可
第7章 函式 7
7.7 類的成員函式 函式原型必須在類中定義。但是,函式體則既可以在類中也可以在類外定義。7.7.1 定義成員函式的函式體 類的所有成員都必須在類定義的花括號裡面宣告,此後,就不能再為類增加任何成員。類的成員函式必須加宣告的一般定義。類的成員函式既可以在類的定義內也可以在類的定義外定義。編譯器隱式地...
C 第8章 函式探幽 知識點總結
c primer plus 第8章知識點總結 c 內聯函式 編譯器將使用相應的函式 替代函式呼叫。對於內聯 程式無需跳到另乙個位置處執行 再跳回來。因此,內聯函式的執行速度比常規函式稍快,但代價是需要占用更多記憶體 要使用內聯函式,必須採取下述措施之一 1 在函式宣告前加上關鍵字inline 2 在...
第7章 函式 4
7.2.5 傳遞給函式的陣列的處理 非引用陣列形參的型別檢查只是確保實參是和陣列元素具有同樣型別的指標,而不會檢查實參實際上是否指向指定大小的陣列。任何處理陣列的程式都要確保程式停留在陣列的邊界內。第一種方法是在陣列本身放置乙個標記來檢測陣列的結束,c風格字串是一種字元陣列,並且以空字元null作為...