一 inline內嵌函式
C++為什麼要內嵌函式,什麼是內嵌函式,內嵌函式的價值是什嗎?
我們已經知道了對於一個常量我們可以使用const代替宏定義,例如 const int A=3; #define A 3
那麼對對於一個函數,是否也可以達到這樣宏替換的效果。
請看:
#define MYFUNC(a, b) ((a) < (b) ? (a) :(b)) // 宏替換的表示inline int myfunc(int a, int b) //函數表示{ returna < b ? a : b;}
這就是內嵌函式。注意一下說明
說明1:
必須inline int myfunc(int a, int b)和函數體的實現,寫在一塊
說明2
C++編譯器可以將一個函數進行內聯編譯
被C++編譯器內聯編譯的函數叫做內嵌函式
內嵌函式在最終產生的程式碼中是沒有定義的
C++編譯器直接將函數體插入在函數調用的地方
內嵌函式沒有普通函數調用時的額外開銷(壓棧,跳轉,返回)——存在價值
說明3:C++編譯器不一定準許函數的內聯請求!
說明4
內嵌函式是一種特殊的函數,具有普通函數的特徵(參數檢查,傳回型別等)
內嵌函式是對編譯器的一種請求,因此編譯器可能拒絕這種請求
內嵌函式由 編譯器處理,直接將編譯後的函數體插入調用的地方
宏程式碼片段 由前置處理器處理, 進行簡單的文本替換,沒有任何編譯過程
說明5:
現代C++編譯器能夠進行編譯最佳化,因此一些函數即使沒有inline聲明,也可能被編譯器內聯編譯
另外,一些現代C++編譯器提供了擴充文法,能夠對函數進行強制內聯
如:g++中的__attribute__((always_inline))屬性
說明6:
C++中內聯編譯的限制:
不能存在任何形式的迴圈語句
不能存在過多的條件判斷語句
函數體不能過於龐大
不能對函數進行取址操作
函數內聯聲明必須在調用語句之前
編譯器對於內嵌函式的限制並不是絕對的,內嵌函式相對於普通函數的優勢只是省去了函數調用時壓棧,跳轉和返回的開銷。
因此,當函數體的執行開銷遠大於壓棧,跳轉和返回所用的開銷時,那麼內聯將無意義。
結論:
1)內嵌函式在編譯時間直接將函數體插入函數調用的地方
2)inline只是一種請求,編譯器不一定允許這種請求
3)內嵌函式省去了普通函數調用時壓棧,跳轉和返回的開銷
二 函數預設參數
C++中可以在函式宣告時為參數提供一個預設值,(需要按照我提供你的值來調用我)
當函數調用時沒有指定這個參數的值,編譯器會自動用預設值代替
void myPrint(int x = 3){printf("x:%d", x);}
函數預設參數的規則
只有參數列表後面部分的參數才可以提供預設參數值
一旦在一個函數調用中開始使用預設參數值,那麼這個參數後的所有參數都必須使用預設參數值
void printAB(int x = 3){printf("x:%d\n",x);}
在預設參數規則,如果預設參數出現,那麼右邊的都必須有預設參數
void printABC(int a, int b, int x = 3, inty=4, int z = 5){printf("x:%d\n",x);}int main62(int argc, char *argv[]){printAB(2);printAB();system("pause");return0;}
三. 函數佔位參數(先佔個坑)
佔位參數只有參數型別宣告,而沒有參數名聲明
一般情況下,在函數體內部無法使用佔位參數
int func(int a, int b, int ) {returna + b;}int main01(){//func(1, 2); //可以嗎?錯誤printf("func(1,2, 3) = %d\n", func(1, 2, 3));getchar(); return0;}
四. 預設參數和佔位參數(結合)
可以將佔位參數與預設參數結合起來使用。 意義: 為以後程式的擴充留下線索 。 相容C語言程式中可能出現的不規範寫法
int func2(int a, int b, int = 0){return a + b;}void main(){//如果預設參數和佔位參數在一起,都能調用起來func2(1,2);func2(1,2, 3);system("pause");}
結論://如果預設參數和佔位參數在一起,都能調用起來
五.函數重載(重點)
1 )函數重載概念
函數重載(FunctionOverload)
用同一個函數名定義不同的函數
當函數名和不同的參數搭配時函數的含義不同
2 )函數重載的判斷標準
函數重載至少滿足下面的一個條件:
參數個數不同
參數類型不同
參數順序不同
3 )函數傳回值不是函數重載的判斷標準
4)編譯器調用重載函數的準則
將所有同名函數作為候選者
嘗試尋找可行的候選函數
精確匹配實參
通過預設參數能夠匹配實參
通過預設類型轉換匹配實參
匹配失敗
最終尋找到的可行候選函數不唯一,則出現二義性,編譯失敗。
無法匹配所有候選者,函數未定義,編譯失敗。
5)函數重載的注意事項
重載函數在本質上是相互獨立的不同函數(靜態鏈編)
重載函數的函數類型是不同的
函數傳回值不能作為函數重載的依據
函數重載是由函數名和參數列表決定的。
六. 函數重載與函數指標的結合
函數重載與函數指標
當使用重載函數名對函數指標進行賦值時
根據重載規則挑選與函數指標參數列表一致的候選者
嚴格匹配候選者的函數類型與函數指標的函數類型
//函數指標 基礎的文法
//1聲明一個函數類型
typedef void (myTypeFunc)(int a,int b) ; //int
//myTypeFunc *myfuncp = NULL; //定義一個函數指標 這個指標指向函數的入口地址
//聲明一個函數指標類型
typedef void (*myPTypeFunc)(int a,int b) ; //聲明了一個指標的資料類型
//myPTypeFunc fp = NULL; //通過 函數指標類型 定義了 一個函數指標 ,
//定義一個函數指標 變數
void (*myVarPFunc)(int a, int b);
//
待補充!
以上就是C++複習要點總結之二——函數的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!