1. 程式人生 > >預設引數,函式過載,引用,行內函數...

預設引數,函式過載,引用,行內函數...

目錄

預設引數 (預設引數)

函式過載

引用

常引用

行內函數

基於範圍的for迴圈

指標空值---nullptr


預設引數 (預設引數)

         定義:指當函式呼叫中省略了實引數時自動使用的一個值。

                    例如: void func(int a = 1){...}

                    呼叫 func() 相當於 func (1);

        全預設引數:所有引數都有預設值 。例: void func (int a = 0, int b = 1, int c = 2)

        半預設引數:部分引數帶有預設值,必須從右往左依次給出 在呼叫賦值從左-->右

        預設引數不能在宣告和定義中同時出現。(最好出現在宣告時)

 注: 預設值是常量或者全域性變數

函式過載

        定義:是函式一種特殊情況,C++允許在同一作用域中宣告幾個功能類似的同名函式

,這些同名函式的形參列表(引數個數、型別、順序)必須不同。 返回值型別是否相同無所謂。

為什麼C語言不支援過載而C++可以?

              在C語言環境下呼叫int型的Add函式:           

                                    

              再呼叫float型的Add函式:

 

              C語言中,編譯器對函式名字的修飾規則:僅在函式名前加"_"。所以當函式過載後,編譯器無法解析它們的不同,所以 C語言不         能過載。

              C++環境下執行的結果:

              C++函式名修飾規則:

Visual C++的名稱修飾規則 :修飾後名字由“?”開頭

                                               函式名由“@”符號結尾的函式名

                                               後面跟著由“@”結尾的類名和名稱空間(此處未建立類和名稱空間所以沒有)

                                               第一個“A”表示函式呼叫型別為“_cdecl”

                                               接著是函式的返回值型別及兩個引數型別,由“@”結束      // int ---> H  ;  double ---> N

                                               最後由“Z”結尾

               所以,由於命名規則的不同,C語言不能函式過載而C++可以。

引用

       概念:引用並不是重新定義一個變數,而是給已存在的變數取別名,對引用的操作與對變數直接操作完全一樣。它會與所引用的變數公用同一塊空間,所以不用再另開闢空間。

       功能: 

            作為函式引數

// 與C語言不同,C++的引用會直接將實參地址當作引數傳遞
void swap(int &A, int &B)
{
    int tmp;
    A = tmp;
    A = B;
    B = tmp;    
}

            從函式中返回左值。

int &Func(int &a)
{
    a += 1;
    return a;
} 

       特性: 

            1. 一個變數可以有多個別名;

            2. 一旦引用一個實體,不能再引用其他實體;

            3. 引用型別必須和引用實體同一型別;   

       

            4. 引用定義必須初始化;

            5. 引用在編譯器中是以const指標實現的,所以它與指標佔相同大小的記憶體;

            6. 由於引用只能引用一個實體,所以它不能引用一個數組(許多元素的集合),但是可以建立陣列的引用;

     

常引用

          通過宣告定義前加const,使得目標變數不可通過引用修改,增加程式碼安全性,健壯性。

          宣告方式:const 型別識別符號 &引用名 = 目標變數名;

引用和指標的不同點:

          1. 引用在定義時必須初始化,指標沒有要求;

          2. 引用在初始化時引用一個實體後,就不能再引用其他實體,而指標可以在任何時候指向任何一個同一型別實體;

          3. 沒有NULL引用,但有NULL指標;

          4. 在sizeof中含義不同:引用結果為引用型別的大小,但指標始終是地址空間所佔位元組個數(32位平臺下佔4位元組);

          5. 引用自加即引用的實體增加1,指標自加即指標後偏移一個型別大小;

          6. 有多級指標,但沒有多級引用;

          7. 訪問實體方式不同,指標需要顯示解引用,引用編譯器自己處理

          8. 引用比指標使用起來相對安全

 

行內函數

            ---既保留了巨集的特性,又比較安全

          以inline修飾的函式叫做行內函數,編譯時C++編譯器會在呼叫行內函數的地方展

  開,沒有函式壓棧的開銷,行內函數提升程式執行的效率,是一個以空間換時間的做法。

  但是加上inline不一定會被當作行內函數,若函式中有遞迴,迴圈,函式較長不適用做行內函數。

          inline對編譯器只是一個建議。

// 由於巨集定義<不開闢棧空間>不安全,產生副作用,不能除錯;所以就有了行內函數。

巨集的優缺點:

          優點:

             1. 增強程式碼的複用性;

             2. 提高效能;

          缺點:

             1. 不方便除錯(預編譯階段進行了替換);

             2. 沒有型別檢測;

             3. 導致程式碼可讀性差,可維護性差,容易誤用。

 C++那些地方可以替換巨集?

       巨集函式 ---》 inline

       巨集變數 ---》 const

 

 

基於範圍的for迴圈

            語法: for(auto 迭代的變數 : 迭代的範圍)

   規則:

            1. for迴圈範圍必須確定:對於陣列,就是陣列的大小;

                                                    對於類,提供begin和end的方法

            2. 迭代物件實現++和==的操作

指標空值---nullptr

      C語言中表示空指標:

            int* p1 = NULL; // NULL是一個巨集

                                     //  定義為:字面常量0 或者 無型別指標(void*)的常量

                                    //   考慮到相容性,保留了NULL

            int* p2 = 0;

      C++11中:

            int* p3 = nullptr;指標空值常量

    nullptr是有型別的,其型別是nullptr_t,僅僅可以被隱式轉化為指標型別;

    注意:

            1. 在使用nullptr表示指標空值時,不需要包含標頭檔案,因為nullptr是C++11作為新關鍵字引入;

            2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所佔位元組數相同;

            3. 為提高程式碼健壯性,在後續表示指標空值時建議最好使用nullptr。