1. 程式人生 > >C++中的行內函數,預設引數和佔位引數

C++中的行內函數,預設引數和佔位引數

說明:裡面的示例程式碼有些被註釋掉了,想執行時要去掉註釋

#include "iostream"
using namespace std;

/** 
    內聯函數出現的原因:
    C++中的const常量可以替代巨集常數定義,如:const int A = 3;#define A 3
    C++中推薦使用行內函數替代巨集程式碼片段
    C++中使用inline關鍵字宣告行內函數
    行內函數宣告時inline關鍵字必須和函式定義結合在一起,否則編譯器會直接忽略內聯請求
    結論:
    1、行內函數在編譯時直接將函式體插入函式呼叫的地方
    2、inline知識一種請求,編譯器不一定允許這種請求
    3、行內函數省去了普通函式呼叫時壓棧,跳轉和返回的開銷
**/
/**
inline void printA()
{
    int a = 10;
    cout<<"a"<<a<<endl;
}
void main()
{
    printA();
    system("pause");
}
**/
/**
    說明:
    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、行內函數省去了普通函式呼叫時壓棧、跳轉和返回的開銷
**/
//帶引數的巨集
#define MYFUNC(a,b) ((a)<(b)?(a):(b))
inline int myfunc(int a,int b)
{
    return a<b? a:b;
}
/**
int main()
{
    int a = 1;
    int b = 3;
    //int d = myfunc(++a,b);//測試行內函數時去掉註釋
    int c = MYFUNC(++a,b);//==>巨集替換並展開 ((++a)<(b)?(++a):(b))
    printf("a=%d\n",a);
    printf("b=%d\n",b);
    printf("c=%d\n",c);
    //printf("d=%d\n",d);

    system("pause");
}
*/
/**============預設餐宿======================**/
/**
    C++中可以在函式宣告時為引數提供一個預設值,當函式呼叫時沒有指定這個引數的值,編譯器會自動用預設值代替
    函式預設引數的規則:
        只有引數列表後面部分的引數才可以提供預設引數值
        一旦在一個函式呼叫中開始使用預設引數值,那麼這個引數後的所有引數都必須使用預設引數值
*/
void myPrint(int x  = 3)
{
    cout<<"x"<<x<<endl;
}
void myPrint(int m,int x  = 3,int y = 4)
{
    cout<<"x"<<x<<endl;
}
/**
    函式佔位引數
    佔位引數只有引數型別宣告,而沒有引數名宣告
    一般情況下,在函式體內部無法使用佔位引數
**/
void func1(int a,int b,int)//呼叫時必須寫夠引數
{
    cout<<"a:"<<a<<" b:"<<b<<endl;
}
/**
    預設引數和佔位引數
    可以將佔位引數與預設引數結合起來使用
    意義:
    為以後程式的擴充套件留下線索   相容C語言程式中可能出現的不規範寫法
    C++可以宣告佔位引數,佔位符引數一般用於程式擴充套件和對C程式碼的相容
**/
int func2(int a,int b,int = 0)
{
    cout<<"a:"<<a<<" b:"<<b<<endl;
    return 0;
}
void main()
{
    //預設引數
    //myPrint(4);
    //myPrint();

    //佔位引數
    func1(1,2,3);
    //佔位引數和預設引數
    func2(4,5);
    func2(1,2,3);
    system("pause");
    return;
}