C++對C語言的擴展(二)

(一)C++中的const

1)C語言與C++中的const 比較:

1° C語言中const變量是隻讀變量,有自己的存儲空間 


2° C++中的const常量可能分配存儲空間,也可能不分配存儲空間  

C語言中的const
#include 
 
int main()
{
    // C語言中 const修飾的變量是一個 常變量,本質還是變量,有自己的地址空間
    const int a = 10;
    int *p = (int *)&a;
 
    *p = 5;
 
    printf ("%d\n", a);
 
    return 0;
}
C++中的const
#include 
 
int main()
{
    // C++中 const 變量聲明的是一個真正的常量,不是變量,所以編譯器不會爲該常量分配空間
    // const 修飾的常量會被放到 符號表 中
    const int a = 10;
 
    // 這裏對 const 常量取地址,這一步操作會讓編譯器爲該變量分配空間,分配的空間並不會被 a 使用
    int *p = (int *)&a;
 
    // 通過指針改變指向的空間的值,這個空間是編譯器爲常量分配的空間,但是常量的值並不在這個空間內
    // 所以即使通過指針修改了這個空間的值,也不會影響到 a 本身
    *p = 5;
 
    // a 的值不變,因爲它的值在符號表中,不在程序運行的空間內
    printf ("%d, %p\n", a, *p);
 
    return 0;
}

2)const與define的比較:

1°相同之處:C++中的const修飾的,是一個真正的常量,而不是C中變量(只讀)。在const修飾的常量編譯期間,就已經確定下來了
2°不同之處:C++中的const常量類似於宏定義 const int c = 5; ≈ #define c 5
C++中的const常量與宏定義不同  const常量是由編譯器處理的,提供類型檢查和作用域檢查 
                                                 宏定義由預處理器處理,單純的文本替換


(二)c++的引用:

1普通引用:

1)變量名回顧:

變量名實質上是一段連續存儲空間的別名,是一個標號(門牌號) 
程序中通過變量來申請並命名內存空間   
通過變量的名字可以使用存儲空間

2)C++引用定義:引用可以看作一個已定義變量的別名,引用的語法:Type& name = var

3)引用的定義:; 

1°引用作爲其它變量的別名而存在,因此在一些場合可以代替指針
2°引用相對於指針來說具有更好的可讀性和實用性

4)引用本質:

引用在C++中的內部實現是一個常指針:  Type& name    =  Type* const name

C++編譯器在編譯過程中使用常指針作爲引用的內部實現,因此引用所佔用的空間大小與指針相同。
 
從使用的角度,引用會讓人誤會其只是一個別名,沒有自己的存儲空間。這是C++爲了實用性而做出的細節隱藏

5)函數返回值爲引用:若返回棧變量  不能成爲其它引用的初始值  不能作爲左值使用

                                  返回全局變量或靜態變量:若返回靜態變量或全局變量  可以成爲其他引用的初始值  即可作爲右值使用,也可作爲左值使用

6)指針引用:傳的是指針引用


2.常引用:分爲倆種情況

    1)用變量初始化 常引用
    {
        int a1 = 20;
        const int& b1 = a1; // a1 變量去初始化常引用
    }
    2)用常量去初始化常引用
    {
        const int a  = 40; // C++編譯器把a放在符號表中
 
        int& b = 41;    // 普通引用,相當於 int *const b引用一個常量,常量是沒有地址空間的,這樣的做法是不合法的
 
        // 使用常量去初始化常引用是合法的,C++編譯器會爲該引用分配空間,常量的值存儲到分配的空間中去
        // 使用常量對 const引用 初始化後,將生成一個只讀變量
        const int& b = 42;




(三)c++中c函數擴展

1.內聯函數:

1)C++中推薦使用內聯函數替代宏代碼片段
72)C++中使用inline關鍵字聲明內聯函數(必須和函數定義放在一起)

3)C++編譯器可以將一個函數進行內聯編譯(inline函數執行時間要儘量短,不要有循環,不要有複雜的判斷)
4)被C++編譯器內聯編譯的函數叫做內聯函數(沒有被inline修飾的普通函數也有可能被編譯器內聯)
5)內聯函數在最終生成的代碼中是沒有定義的
6)C++編譯器直接將函數體插入在函數調用的地方 (宏代碼片段 由預處理器處理, 進行簡單的文本替換,沒有任何編譯過程)
7)內聯函數沒有普通函數調用時的額外開銷(壓棧,跳轉,返回)

8)內聯函數是對編譯器的一種請求,C++編譯器不一定準許函數的內聯請求!

例如:C++中內聯函數的實現機制

inline int func(int a, int b)
{
       return a < b ? a : b;
}

int main()
{
       int r = func(1,2);

       return 0;
}
將內聯函數func存入符號表 然後用符號表中的函數體替換func調用

2.默認參數:

1)定義:C++中可以在函數聲明時爲參數提供一個默認值,當函數調用時沒有指定這個參數的值,編譯器會自動用默認值代替
2)規則:只有參數列表後面部分的參數纔可以提供默認參數值, 一旦在一個函數調用中開始使用默認參數值,那麼這個參數後的所有參數都必須使用默


3佔位參數:

佔位參數只有參數類型聲明,而沒有參數名聲明,一般情況下,在函數體內部無法使用佔位參數


4函數重載:

1)定義:函數名相同 根據函數的參數不同會調用不同的函數

2)規則:1°函數返回值不能作爲函數重載的判定

               2°參數類型不同,參數個數不同,參數的順序不同

3)注意點:1°函數重載和函數默認參數一起使用,可能會導致調用關係不明確

                   2°重載函數賦值給一個函數指針,要精確匹配函數指針的類型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章