函数重载、引用再探、内联函数
文章目錄
- 函數(shù)重載
- 為什么C++支持重載,C語(yǔ)言不支持呢?
- extern “C”
- 引用再探
- 引用的特性
- 引用的使用場(chǎng)景
- 引用和指針
- 引用和指針的不同點(diǎn):
- 內(nèi)聯(lián)函數(shù)
- 什么是內(nèi)聯(lián)函數(shù)?
- 內(nèi)聯(lián)函數(shù)的特性
- 內(nèi)聯(lián)函數(shù)的好處
- 類(lèi)的內(nèi)聯(lián)成員函數(shù)的聲明
- constexpr函數(shù)
- 概念
- 特征
- 內(nèi)聯(lián)函數(shù)和constexpr函數(shù)放在頭文件內(nèi)
函數(shù)重載
在同一個(gè)作用域下,對(duì)于相同的函數(shù)名,函數(shù)的參數(shù)類(lèi)型不同,參數(shù)順序不同,參數(shù)的個(gè)數(shù)不同, 都可以形成函數(shù)的重載(參數(shù)名不同,返回值不同不形成重載)
函數(shù)的重載主要用于處理功能相同,形參類(lèi)型不同的數(shù)據(jù)。
void test(int i, int j) {cout << "test" << endl; }void test(double i, int j) // 類(lèi)型不同 {cout << "test" << endl; }void test(int j, double i) // 順序不同 {cout << "test" << endl; }void test(double i, int j, int k) // 個(gè)數(shù)不同 {cout << "test" << endl; }為什么C++支持重載,C語(yǔ)言不支持呢?
因?yàn)閣indows對(duì)函數(shù)重載的處理更加復(fù)雜,所以這里用linux下的gcc和g++來(lái)看更加直觀。
首先我們要知道,鏈接器看到有函數(shù)被調(diào)用的時(shí)候,就會(huì)到符號(hào)表中去查找對(duì)應(yīng)的函數(shù)名,來(lái)獲取函數(shù)的地址,再鏈接到一起
先看C語(yǔ)言是怎么處理的
通過(guò)反匯編我們可以看到,C語(yǔ)言并沒(méi)有對(duì)函數(shù)名進(jìn)行處理,也就是說(shuō)無(wú)論我們參數(shù)的個(gè)數(shù),參數(shù)的類(lèi)型,參數(shù)的順序怎么修改,它只認(rèn)函數(shù)名,如果出現(xiàn)了第二個(gè)相同函數(shù)名的,就算重定義。
下面再看C++的:
這里可以看到,C++對(duì)函數(shù)名進(jìn)行了處理,函數(shù)以_Z4開(kāi)頭,接著是函數(shù)名,最后是所有參數(shù)的縮寫(xiě)。
_Z是所有函數(shù)的前綴,4是函數(shù)名的字符個(gè)數(shù),例如第一個(gè)_Z4testii則代表函數(shù)名為test,具有四個(gè)字符,參數(shù)類(lèi)型縮寫(xiě)分別是ii。
這也就是為什么返回值不同和參數(shù)名不構(gòu)成重載的原因,它們不被作為對(duì)函數(shù)特征的處理。C++正是通過(guò)這種函數(shù)名修飾規(guī)則來(lái)實(shí)現(xiàn)函數(shù)的重載。
extern “C”
有時(shí)候我們?cè)谑褂肅++的時(shí)候,對(duì)于某些函數(shù),想讓它按照C的風(fēng)格來(lái)編譯,那么就在函數(shù)前加extern “C”,意思是告訴編譯器,將該函數(shù)按照C語(yǔ)言規(guī)則來(lái)編譯。
引用再探
引用的特性
引用的使用場(chǎng)景
假設(shè)我們存在一個(gè)超級(jí)大的結(jié)構(gòu)體,如果我們直接將結(jié)構(gòu)體傳過(guò)去的話(huà),會(huì)產(chǎn)生一個(gè)臨時(shí)變量來(lái)將這個(gè)結(jié)構(gòu)體拷貝到形參中,這是極大的開(kāi)銷(xiāo),但如果我們使用引用的話(huà),傳的只是一個(gè)別名而已,所有的操作還是在結(jié)構(gòu)體本身上進(jìn)行的,但是需要注意的和上面一樣,如果我們要傳遞一個(gè)常量,就必須要在引用前加上const。
struct A {int arr[1000000]; };void test (const A& s1) {} int main(int argc, char const *argv[]) {const A a = {10,324,32};test(a);return 0; }對(duì)于這樣一個(gè)代碼,我們可能第一眼覺(jué)得ret會(huì)是3。
但是其實(shí)是7。
因?yàn)槲覀兎祷氐氖莄的一個(gè)引用,但是c只存在于調(diào)用時(shí)的那個(gè)棧幀,調(diào)用結(jié)束后那個(gè)棧幀就會(huì)被銷(xiāo)毀,雖然銷(xiāo)毀后數(shù)據(jù)不會(huì)被清空,但是那片區(qū)域的訪問(wèn)權(quán)限就會(huì)被放開(kāi),有可能會(huì)被下次調(diào)用的函數(shù)使用,也有可能會(huì)被其他的一個(gè)操作給使用,所以這是一種極為不安全的行為。
上面的7是第二次調(diào)用后修改了c的值。
所以,如果需要引用作為返回值,就必須保證出了函數(shù)作用域,返回的對(duì)象沒(méi)有歸還給系統(tǒng),仍然存在。
以值作為參數(shù)或者返回值時(shí),在傳參和返回的時(shí)候,都會(huì)傳遞或返回原變量的一個(gè)臨時(shí)的拷貝,這樣的效率是非常低下的,尤其是數(shù)據(jù)特別大的時(shí)候,但如果使用引用作為參數(shù)的話(huà),就不會(huì)有這樣的問(wèn)題。
引用和指針
語(yǔ)法概念上:引用是對(duì)象的一個(gè)別名,沒(méi)有獨(dú)立的空間,和其引用的實(shí)體共用一個(gè)空間。
但我們發(fā)現(xiàn),引用其實(shí)和指針很像,它更像一個(gè)頂層const的指針,所以我們可以進(jìn)入反匯編看看他們之間有沒(méi)有關(guān)系
int main() {int x = 5;int& y = x;int* z = &x;return 0; }
反匯編下我們可以看到,指針和引用在匯編下的實(shí)現(xiàn)是一模一樣的。
所以我們可以得出一個(gè)結(jié)論:引用是按照指針來(lái)實(shí)現(xiàn)的,在指針的基礎(chǔ)上又給他封裝了新的功能。
引用和指針的不同點(diǎn):
內(nèi)聯(lián)函數(shù)
什么是內(nèi)聯(lián)函數(shù)?
用inline關(guān)鍵字修飾的函數(shù)就是內(nèi)聯(lián)函數(shù),在編譯時(shí)編譯器會(huì)將函數(shù)的代碼在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開(kāi),減去了函數(shù)壓棧的開(kāi)銷(xiāo),提升程序運(yùn)行的效率(犧牲空間換取時(shí)間)。
例如這樣一個(gè)簡(jiǎn)單的代碼
如果我們直接調(diào)用它
在匯編下可以看到,他會(huì)創(chuàng)建一個(gè)新的棧幀,將參數(shù)3,4壓棧,然后計(jì)算完再返回結(jié)果
而如果在函數(shù)前面加上inline使其變?yōu)閮?nèi)聯(lián)函數(shù)
這時(shí)再看,就會(huì)發(fā)現(xiàn)它直接把函數(shù)的代碼在調(diào)用處直接展開(kāi),不會(huì)再創(chuàng)建新的棧幀。
內(nèi)聯(lián)函數(shù)的特性
值得一提的是,內(nèi)聯(lián)函數(shù)與C語(yǔ)言中的宏函數(shù)有些類(lèi)似,雖然宏的性能不錯(cuò),但是因?yàn)楹耆狈︻?lèi)型的安全檢查和無(wú)法調(diào)試(在預(yù)處理階段就進(jìn)行了宏替換),在C++中宏函數(shù)被內(nèi)聯(lián)函數(shù)替代,宏常量定義被const取代。
內(nèi)聯(lián)函數(shù)的好處
類(lèi)的內(nèi)聯(lián)成員函數(shù)的聲明
我們可以在類(lèi)內(nèi)把inline作為聲明的一部分顯式地聲明成員函數(shù),同樣的,也能在類(lèi)的外部用inline關(guān)鍵字修飾函數(shù)的定義(當(dāng)然在聲明和定義的地方同時(shí)說(shuō)明inline也是合法,只是沒(méi)有必要)。
constexpr函數(shù)
概念
能用于常量表達(dá)式的函數(shù)
特征
內(nèi)聯(lián)函數(shù)和constexpr函數(shù)放在頭文件內(nèi)
和其他函數(shù)不同,內(nèi)聯(lián)函數(shù)和constexpr可以在程序中多次定義(每一次展開(kāi)就是一次定義)。但多個(gè)定義必須完全一致,基于這個(gè)原因,內(nèi)聯(lián)函數(shù)和constexpr函數(shù)通常定義在頭文件。
總結(jié)
以上是生活随笔為你收集整理的函数重载、引用再探、内联函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2022年办理银行卡为什么要证明,要保证
- 下一篇: 【精品计划 附录2】- 算法分析