您當前的位置:首頁 > 攝影

C++內聯與引用

作者:由 小浩 發表于 攝影時間:2022-11-11

今天來給大家介紹一些關於C++內聯與引用方面的知識

先來說說我自己的認知。

第一:行內函數

目的:為了提高執行速度

那麼為什麼可以提高執行速度呢?

首先原始的函式呼叫要經過幾個過程:call儲存函式執行前的地址->傳遞形參->開闢棧區並跳轉到函式->開始執行->根據儲存的地址跳回原執行的步驟。

而行內函數,不會執行跳轉和儲存地址的操作,它會將函式的程式碼直接在呼叫函式處展開,(更為準確的理解是:在程式編譯時,編譯器將程式中出現的行內函數的呼叫表示式用行內函數的函式體來進行替換),就節省了跳轉和儲存地址等操作的時間(主要是跳轉的時間)

綜上所述,行內函數是否節省時間,主要還是對比跳轉和原地展開函式的多使用的記憶體間的利弊。

舉個例子:如果一個一個函式執行2s,那麼內聯節省的幾ms的時間幾乎沒有意義,同時反而浪費了大量的記憶體,使得程式碼體積變大。

從行內函數的實際使用原理這裡我們可以發現,行內函數的侷限性,由侷限性推出其使用場景:

1。適用於頻繁呼叫的,比較簡單的函式。

比如說:遞迴函式無法內聯,多重迴圈也不內聯,含有switch或goto的函式

注意的點:

1。在使用行內函數時,只需要在函式的宣告或者函式原型前加一個inline 就可以了(C++ Primer Plus這麼說的),但是在實際使用的過程中有些問題存在,必須要在要在函式定義處新增 inline 關鍵字,在函式宣告處新增 inline 關鍵字雖然沒有錯,但這種做法是無效的,編譯器會忽略函式宣告處的 inline 關鍵字。(就像是函式的宣告處的形參名即使和函式定義的形參命不一樣,也不會報錯,因為編譯器根本就忽略了宣告中的形參名)

2。inline只是一個對於編譯器的建議,不是強制型別的,就如同C語言中的register,具體是否採用建議,取決於編譯器。

一些關於行內函數的預備知識:

1。在類中定義的成員函式預設為行內函數,但是如果是在類外定義的成員函式就不是預設的行內函數,如果要在類外定義內聯的成員函式就需要在定義前加上inline,並且類的定義要和類外內聯成員函式的定義在同一個源程式檔案中。

2。行內函數是沒有地址的,如果能從這點入手,那麼關於內聯的很多問題和侷限都能弄明白了。

第二點:關於引用

C++種引用的出現是對C語言的一大突破,那麼引用是個什麼意思呢?通俗的來解釋就是給一個變數取了多個名字,值和地址都相同,比如,一個人可以叫張三,也可以說是小張,都是指得同一個人。概念和定義確實很好解釋,但是引用最棘手的部分還是它的應用。

插入一條小知識:C++函式對於C語言的函式突破主要有哪些呢?1。函式預設引數2。函式的過載(多型)3。模板4。繼承5。引用傳參

重難點(1):臨時變數,引用引數和const

首先引入一個它的特點:引用傳參的限制要比普通的傳地址或者傳值複雜的多,也靈活的多,用的好,那叫一個6,用不好就是一堆Bug。

1。傳引用呼叫函式時,(嚴格來說)函式的實參列表不能是表示式,而必須是變數,如果非要傳表示式得話,那麼形參型別應為const Datetype & 名

我們知道形似int add(int a,int b); void size(int *a,int*b);之類得函式我們呼叫時是可以傳表示式的。但是如果形參為int & 之類就不行,原因是:

表示式不是變數

怎麼解釋呢?可以從這些不同得傳引數的結果來比較

傳值,我們形參得到的是實參的複製;傳地址,我們得到的也只是地址的一份複製,只不過我們可以透過這個複製的地址來對變數的實體進行操作而已;但是,傳引用,我們得形參得到的就是實參本身。傳值可以理解為只是想使用變數的值,傳地址可以理解為間接地操作變數本身,而傳引用兼具了前兩者,你可以直接用變數的值,也可以操作變數本身。形如x+3這種表示式,他不是一個變數,形參int & x就找不到實體,所以這是被被允許的。後面介紹為什麼說使用const &地形參定義就又可以。

老版本種其實對於引用型別的形參傳遞x+3的行為是允許的,這時系統會自動建立一個臨時的變數作為改形參的引用。

我們來看看什麼時候建立臨時變數,如果引用引數為const,那麼,一:實參型別正確,但不是左值;二:實參的型別不正確,但可以轉換為正確的型別

首先來了解什麼是左值,就是可引用的資料物件,例如:結構體,變數,陣列元素,結構體成員,解引用的指標,const變數(不可修改的左值)。

對於這些生成的匿名變數,它們只在函式呼叫的期間存在。那麼為什麼要用const修飾呢?簡而言之,如果目的是為了修改作為引數傳遞的變數,則建立臨時變數無法完成這一目的,而C++的解決方法就是禁止建立臨時變數,為了不使用C++的方法,我們自己使用const保證了改引數不被修改;而如果函式的目的只是想使用該引數的值,那麼臨時變數不會造成什麼影響。

綜上,對於C++中被const修飾的形參,如果實參不匹配,則其行為類似於按值傳遞。讓形參來引用該匿名變數。

插入一段函式呼叫使用const修飾的好處。

1。確保了傳遞的引數不被修改。2。拓寬了可傳遞引數的類別,讓形參可接受const和非const型別3。在C++中使得函式可以正確生成並使用匿名變數

重難點(2)

引用作為返回值。

在這裡我們需要更加深入的理解函式返回的機制:返回引用的函式實際上是被引用的變數的別名;而對於返回不是引用的函式,看似是返回一個區域性變數(形參),但是其實在返回時,這個形參被複製了一份(匿名變數),最終是這個匿名變量回到函式呼叫處,將值賦給相應的變數

區別引用返回值和常規返回

常規返回,返回的是一個值,也就是右值,即不能透過地址訪問的值,右值可以出現在賦值表示式的右邊而不能出現在左邊,深層原因是因為這種常規的返回值位於臨記憶體單元中,執行到下一條語句時,他可能就不存在了。

引用返回,返回的是一個實在的物件,它是穩定存在的,所以可以充當左值,而如果我們並不想讓這個引用的返回值被修改或者賦值,那麼我們就只能定義返回型別為const +引用

最後補充一些零零散散的知識點:

C++string類定義了一種char *到string的轉換功能,這就使得可以使用C風格的字串來初始化string物件

標簽: 函式  內聯  變數  引用  const