引用和內聯函式

2022-08-24 00:03:14 字數 3555 閱讀 6225

內聯函式是c++為提高程式執行速度所做的一項改進。

編譯過程的最終產品是可執行程式(由一組機器語言指令組成)。程式執行時,作業系統將這些指令載入到計算機記憶體中,因此每條指令都有特定的記憶體位址。

常規函式呼叫過程---程式跳到函式的位址,並在函式結束時返回。即,程式執行到函式呼叫指令時,將在函式呼叫後立即儲存該指令的記憶體位址,並將函式引數複製到堆疊,跳到標記函式起點的記憶體單元,執行函式**,返回值放入暫存器中,然後跳回到位址被儲存的指令處(這與閱讀文章時停下來看標註,並在閱讀完標註後返回到之前閱讀的地方類似)

內聯函式是將相應的**替換函式呼叫。優點是內聯函式執行速度比常規函式稍快,缺點是占用更多記憶體。

要使用內聯函式,需要:

(1)在函式宣告前加上關鍵字inline

(2)在函式定義前加上關鍵字inline

注:內聯函式不能遞迴

另:內聯函式與巨集的區別

內聯函式引數傳遞方式與常規函式一樣,巨集是簡單的文字替換來完成

例如:inline double square(double x)

#define square(x) x*x

square(0.5)  //->0.5*0.5

square(4.5+7.5)

square(c++) //c++*c++

引用時已定義的變數的別名(如土豆,又叫馬鈴薯)。引用的主要用途是用作函式的形參。通過引用傳遞引數,函式會訪問使用原始資料,而不是像按值傳遞一樣使用副本。

int

rats;

int & rodents = rats;//rodents為rats的引用,即別名 這兩個值表明的是同乙個事物,同一塊記憶體同乙個位址同乙個值

特點:與const指標比較接近,必須在宣告引用變數時進行初始化。一旦與某個變數關聯,就將一直效忠與它。

引用與變數一體,共用同一塊記憶體,看好引用的記憶體和值即可。陣列不能宣告引用

引用作為函式引數,原理是將函式中變數名成為呼叫程式中的變數的別名。

按值傳遞

void sneezy(int

x);int

main()

void sneezy(int x)//建立x變數,將傳遞來的值賦值給x

2個變數,兩個名字,x和times除了值相同,完全兩個變數,沒有任何聯絡

按引用傳遞

void grumpy(int

&x);

intmain()

void grumpy(int &x)//x為times的別名

times和x是同乙個變數,只不過有兩個名稱

函式呼叫使用實參初始化形參,因此函式的引用引數被初始化為函式呼叫傳遞的實參。

如果實參和引用引數型別不匹配,c++將生成臨時變數。僅當引數為const引用時,c++才允許這樣使用不會報錯。

關於臨時變數,如果引用引數時const,則下面兩種情況下生成臨時變數(匿名變數)

實參的型別正確,但不是左值。

實參的型別不正確,但可以轉換為正確的型別

double refcube(const

double &ra)//僅當為常量引用,可以允許下面的情況,因為不修改ra的值,所以是不是臨時變數無所謂

intmain()

; refcube(side);

refcube(lens[

2]);

refcube(*pd);

refcube(edge);//生產臨時變數

refcube(

7.0);//生產臨時變數

refcube(side+7.0

);//生產臨時變數

const

double & p12 = 0.1+0.2

; system(

"pause");

return0;

}

為什麼非const引用不可以這樣操作?

理解如下:

void swapr(int &a, int &b)

long a = 3, b = 5;

swapr(a,b);

上述實參型別和形參的引用型別不匹配,編譯器會建立兩個臨時int變數,將其初始化為3和5,然後交換臨時變數的值,實參的值不變

乙個接受引用引數的函式的目的就是修改實參的值,如果建立臨時變數,就阻止了函式的這一作用。

實際上,對於形參為const引用的c++函式,如果實參不匹配,則其行為類似於按值傳遞,為確保原始資料不被修改,將使用臨時變數來儲存值。

將引用引數宣告為常量資料的引用的理由:

1)使用const可以避免無意中修改資料的程式設計錯誤

2)使用const使函式能夠處理const和非const實參,否則將只能接受非const資料

3)使用const引用能使函式能夠正確生成並使用臨時變數

引用非常適合用於結構和類,引用主要是為了用於這些型別,而不是基本的內建型別

struct free_throws

free_throws dup;

free_throws four = ;

free_throws five = ;

free_throws & accumulate(free_throws & target, const free_throws & source);

accumulate(dup, five) = four;//不常用,作為乙個例子解釋下面問題

1.函式形參為引用:與按值傳遞相比,引用傳遞少了複製拷貝原始結構這一步,可以節省時間和記憶體。

2.函式返回值為引用:傳統返回機制會計算return後變數(這個值被複製到乙個臨時位置),並將結果返回給呼叫函式,

例:dup = accumulate(four, five);

如果accumulate返回乙個結構,不是引用,會將整個結構複製到乙個臨時位置,再將這個拷貝複製給dup

現在是引用,會直接把函式中return的值複製給dup,效率更高

4.返回引用時應注意:避免返回函式終止時不再存在的記憶體單元引用。1)返回乙個作為引數傳遞給函式的引用  2)用new來分配新的儲存空間,返回指向該空間的指標

5.可以將const用於引用返回型別,避免返回值被改變

accumulate(dup, five) = four;可以通過編譯,但是若此函式返回值為結構體,則不能通過編譯

原因:在賦值語句中,左邊必須是可以修改的左值,即左邊的子表示式必須標識乙個可修改的記憶體塊,此函式返回值為結構體引用時,函式返回dup的引用,它確實標識的時乙個這樣的記憶體塊,所以

可以編譯通過

常規(非引用)返回型別是右值---不能通過位址訪問的值,這種表示式可以出現在賦值語句的右邊,但是不能出現在左邊。其他右值包括字面值如10.0和表示式如x+y。獲取字面值的位址

沒有意義,但是為何常規函式返回值是右值呢,因為這種返回值位於臨時記憶體單元中,執行到下一條語句時,它們可能就不在存在了。

類中有乙個特徵,基類引用可以指向派生類物件,無需進行強制型別轉換。

可以定義乙個接受基類引用作為引數的函式,呼叫該函式時,可以將基類物件作用引數,也可以將派生類物件作為引數。

內聯inline函式和引用

inline函式 函式呼叫點 直接展開 文字替換 沒了開棧和清棧的開銷,效率高 inline int sum int a,int b return a b 1.inline 函式和普通函式的區別 inline函式只能在本檔案可見 2.inline函式和static修飾的函式的區別 有呼叫函式的開銷 ...

C 內聯函式和引用變數

內聯函式和普通函式的使用方法沒有本質區別,我們來看乙個例子,下面展示了內聯函式的使用方法 include using namespace std 下面展示內聯函式的使用 inline double square doublex intmain 從上面我們可以看到我們定義乙個內聯函式只需要在普通函式的...

函式過載 引用 內聯函式

預設引數 在定義或者宣告乙個函式的時候,給它的形參賦上乙個預設值,呼叫這個函式的時候,如果沒有把實參傳入,函式就會使用我們指定的預設引數,如果傳入實參,就會使用傳入的引數。預設引數可分為 全預設引數 在這個函式中,給所有的形參都指定了預設值。半預設引數 在這個函式中,只給一部分的形參指定了預設值。注...