C到C++的擴充

mf1crystal發表於2018-01-08

C++的引用:

變數名的回顧:變數名實質上是一段連續儲存空間的別名,是一個標號(門牌號) 
程式中通過變數來申請並命名記憶體空間   
通過變數的名字可以使用儲存空間

C++中的引用:

#include <stdio.h>
int main()
{
    // 定義一個int型變數a,在記憶體中佔4個位元組,
    // 變數名 a 就代表了這一塊記憶體,或者說 a 是這塊記憶體的別名
    int a = 10; 
    // 定義了一個引用變數 b ,它是 a 的別名,和 a 代表同一塊記憶體空間
    // 對 b 的操作 和 對 a 的操作是一樣的
    int& b = a; 
    // 改變 b 等於改變了 a
    b = 20; 
    printf ("%d, %d\n", a, b); 
    // a 與 b 代表同一塊記憶體空間
    printf ("%p, %p\n", &a, &b);
    return 0;
}

引用的本質:

引用在C++中的內部實現是一個常指標
        Type& name      Type* const name
 
C++編譯器在編譯過程中使用常指標作為引用的內部實現,因此引用所佔用的空間大小與指標相同。
 
從使用的角度,引用會讓人誤會其只是一個別名,沒有自己的儲存空間。這是C++為了實用性而做出的細節隱藏
 
當我們使用引用語法的時,我們不去關心編譯器引用是怎麼做的
    當我們分析奇怪的語法現象的時,我們才去考慮c++編譯器是怎麼做的

指標的引用:

#include "iostream"
using namespace std;
 
struct Teacher
{
    char name[64];
    int age ;
};
 
//在被呼叫函式 獲取資源
int getTeacher(Teacher **p)
{
    Teacher *tmp = NULL;
    if (p == NULL)
    {
        return -1;
    }
    tmp = (Teacher *)malloc(sizeof(Teacher));
    if (tmp == NULL)
    {
        return -2;
    }
    tmp->age = 33;
    // p是實參的地址  *實參的地址 去間接的修改實參的值
    *p = tmp;
}
  
//指標的引用 做函式引數
void getTeacher2(Teacher* &myp)
{
    //給myp賦值 相當於給main函式中的pT1賦值
    myp = (Teacher *)malloc(sizeof(Teacher));
    if (myp == NULL)
    {
        return;
    }
    myp->age = 36;
}
 
void FreeTeacher(Teacher *pT1)
{
    if (pT1 == NULL)
    {
        return ;
    }
    free(pT1);
}
 
int main()
{
    Teacher *pT1 = NULL;
 
    //1 c語言中的二級指標
    getTeacher(&pT1);
    cout<< "age:" << pT1->age << endl;
    FreeTeacher(pT1);
 
 
    //2 c++中的引用 (指標的引用)
    getTeacher2(pT1);
 
    cout << "age:" << pT1->age << endl;
    FreeTeacher(pT1);
 
    cout << "hello..." << endl;
 
    return 0;
}
 

C++對C函式的擴充:

行內函數:行內函數宣告時inline關鍵字必須和函式定義結合在一起,否則編譯器會直接忽略內聯請求

C++編譯器可以將一個函式進行內聯編譯
被C++編譯器內聯編譯的函式叫做行內函數
行內函數在最終生成的程式碼中是沒有定義的
C++編譯器直接將函式體插入在函式呼叫的地方 
行內函數沒有普通函式呼叫時的額外開銷(壓棧,跳轉,返回

行內函數是一種特殊的函式,具有普通函式的特徵(引數檢查,返回型別等)
行內函數是對編譯器的一種請求,因此編譯器可能拒絕這種請求
行內函數由 編譯器處理,直接將編譯後的函式體插入呼叫的地方
巨集程式碼片段 由前處理器處理, 進行簡單的文字替換,沒有任何編譯過程

預設引數:

C++中可以在函式宣告時為引數提供一個預設值,
當函式呼叫時沒有指定這個引數的值,編譯器會自動用預設值代替只有引數列表後面部分的引數才可以提供預設引數值
 一旦在一個函式呼叫中開始使用預設引數值,那麼這個引數後的所有引數都必須使用默

函式的過載:

用同一個函式名定義不同的函式
當函式名和不同的引數搭配時函式的含義不同 

呼叫函式過載的準則:

將所有同名函式作為候選者
 嘗試尋找可行的候選函式:
          1 )精確匹配實參
          2) 通過預設引數能夠匹配實參
          3) 通過預設型別轉換匹配實參
匹配失敗:
          1) 最終尋找到的可行候選函式不唯一,則出現二義性,編譯失敗。
          2) 無法匹配所有候選者,函式未定義,編譯失敗。

函式過載的注意事項:

過載函式在本質上是相互獨立的不同函式(靜態鏈編)
過載函式的函式型別是不同的
函式返回值不能作為函式過載的依據
函式過載是由函式名和引數列表決定的。







相關文章