欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ 關(guān)鍵字 inline詳細(xì)介紹

 更新時(shí)間:2014年01月26日 16:16:24   投稿:shangke  
這篇文章主要介紹了C++ 關(guān)鍵字 inline,有需要的朋友可以參考一下

1.  內(nèi)聯(lián)函數(shù)

在C++中我們通常定義以下函數(shù)來求兩個(gè)整數(shù)的最大值:

復(fù)制代碼 代碼如下:

int max(int a, int b)
{
 return a > b ? a : b;
}

為這么一個(gè)小的操作定義一個(gè)函數(shù)的好處有:

① 閱讀和理解函數(shù) max 的調(diào)用,要比讀一條等價(jià)的條件表達(dá)式并解釋它的含義要容易得多

② 如果需要做任何修改,修改函數(shù)要比找出并修改每一處等價(jià)表達(dá)式容易得多

③ 使用函數(shù)可以確保統(tǒng)一的行為,每個(gè)測(cè)試都保證以相同的方式實(shí)現(xiàn)

④ 函數(shù)可以重用,不必為其他應(yīng)用程序重寫代碼

雖然有這么多好處,但是寫成函數(shù)有一個(gè)潛在的缺點(diǎn):調(diào)用函數(shù)比求解等價(jià)表達(dá)式要慢得多。在大多數(shù)的機(jī)器上,調(diào)用函數(shù)都要做很多工作:調(diào)用前要先保存寄存器,并在返回時(shí)恢復(fù),復(fù)制實(shí)參,程序還必須轉(zhuǎn)向一個(gè)新位置執(zhí)行

C++中支持內(nèi)聯(lián)函數(shù),其目的是為了提高函數(shù)的執(zhí)行效率,用關(guān)鍵字 inline 放在函數(shù)定義(注意是定義而非聲明,下文繼續(xù)講到)的前面即可將函數(shù)指定為內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)通常就是將它在程序中的每個(gè)調(diào)用點(diǎn)上“內(nèi)聯(lián)地”展開,假設(shè)我們將 max 定義為內(nèi)聯(lián)函數(shù):

復(fù)制代碼 代碼如下:

inline int max(int a, int b)
{
 return a > b ? a : b;
}

則調(diào)用: cout<<max(a, b)<<endl;


在編譯時(shí)展開為: cout<<(a > b ? a : b)<<endl;

從而消除了把 max寫成函數(shù)的額外執(zhí)行開銷

2.  內(nèi)聯(lián)函數(shù)和宏

無論是《Effective C++》中的 “Prefer consts,enums,and inlines to #defines” 條款,還是《高質(zhì)量程序設(shè)計(jì)指南——C++/C語言》中的“用函數(shù)內(nèi)聯(lián)取代宏”,宏在C++中基本是被廢了,在書《高質(zhì)量程序設(shè)計(jì)指南——C++/C語言》中這樣解釋到:

3.  將內(nèi)聯(lián)函數(shù)放入頭文件

關(guān)鍵字 inline 必須與函數(shù)定義體放在一起才能使函數(shù)成為內(nèi)聯(lián),僅將 inline 放在函數(shù)聲明前面不起任何作用。

如下風(fēng)格的函數(shù) Foo 不能成為內(nèi)聯(lián)函數(shù):

復(fù)制代碼 代碼如下:

inline void Foo(int x, int y);   // inline 僅與函數(shù)聲明放在一起  
void Foo(int x, int y)
{
 ...
}

而如下風(fēng)格的函數(shù) Foo 則成為內(nèi)聯(lián)函數(shù):

復(fù)制代碼 代碼如下:

void Foo(int x, int y);  
inline void Foo(int x, int y)   // inline 與函數(shù)定義體放在一起
{
 ...
}

所以說,C++ inline函數(shù)是一種“用于實(shí)現(xiàn)的關(guān)鍵字”,而不是一種“用于聲明的關(guān)鍵字”。一般地,用戶可以閱讀函數(shù)的聲明,但是看不到函數(shù)的定義。盡管在大多數(shù)教科書中內(nèi)聯(lián)函數(shù)的聲明、定義體前面都加了 inline 關(guān)鍵字,但我認(rèn)為 inline 不應(yīng)該出現(xiàn)在函數(shù)的聲明中。這個(gè)細(xì)節(jié)雖然不會(huì)影響函數(shù)的功能,但是體現(xiàn)了高質(zhì)量C++/C 程序設(shè)計(jì)風(fēng)格的一個(gè)基本原則:聲明與定義不可混為一談,用戶沒有必要、也不應(yīng)該知道函數(shù)是否需要內(nèi)聯(lián)。

定義在類聲明之中的成員函數(shù)將自動(dòng)地成為內(nèi)聯(lián)函數(shù),例如:

復(fù)制代碼 代碼如下:

class A

public:
 void Foo(int x, int y) { ... }   // 自動(dòng)地成為內(nèi)聯(lián)函數(shù) 
}

但是編譯器是否將它真正內(nèi)聯(lián)則要看 Foo函數(shù)如何定義

內(nèi)聯(lián)函數(shù)應(yīng)該在頭文件中定義,這一點(diǎn)不同于其他函數(shù)。編譯器在調(diào)用點(diǎn)內(nèi)聯(lián)展開函數(shù)的代碼時(shí),必須能夠找到 inline 函數(shù)的定義才能將調(diào)用函數(shù)替換為函數(shù)代碼,而對(duì)于在頭文件中僅有函數(shù)聲明是不夠的。

當(dāng)然內(nèi)聯(lián)函數(shù)定義也可以放在源文件中,但此時(shí)只有定義的那個(gè)源文件可以用它,而且必須為每個(gè)源文件拷貝一份定義(即每個(gè)源文件里的定義必須是完全相同的),當(dāng)然即使是放在頭文件中,也是對(duì)每個(gè)定義做一份拷貝,只不過是編譯器替你完成這種拷貝罷了。但相比于放在源文件中,放在頭文件中既能夠確保調(diào)用函數(shù)是定義是相同的,又能夠保證在調(diào)用點(diǎn)能夠找到函數(shù)定義從而完成內(nèi)聯(lián)(替換)。

但是你會(huì)很奇怪,重復(fù)定義那么多次,不會(huì)產(chǎn)生鏈接錯(cuò)誤?

我們來看一個(gè)例子:

A.h :

復(fù)制代碼 代碼如下:

class A
{
public:
 A(int a, int b) : a(a),b(b){}
 int max();

private:
 int a;
 int b;
};

A.cpp :

復(fù)制代碼 代碼如下:

#include "A.h"

inline int A::max()
{
 return a > b ? a : b;
}

Main.cpp :

復(fù)制代碼 代碼如下:

#include <iostream>
#include "A.h"
using namespace std;

inline int A::max()
{
 return a > b ? a : b;
}

int main()
{
 A a(3, 5);
 cout<<a.max()<<endl;
 return 0;
}

一切正常編譯,輸出結(jié)果:5


倘若你在Main.cpp中沒有定義max內(nèi)聯(lián)函數(shù),那么會(huì)出現(xiàn)鏈接錯(cuò)誤:

error LNK2001: unresolved external symbol "public: int __thiscall A::max(void)" (?max@A@@QAEHXZ)main.obj
找不到函數(shù)的定義,所以內(nèi)聯(lián)函數(shù)可以在程序中定義不止一次,只要 inline 函數(shù)的定義在某個(gè)源文件中只出現(xiàn)一次,而且在所有源文件中,其定義必須是完全相同的就可以。

在頭文件中加入或修改 inline 函數(shù)時(shí),使用了該頭文件的所有源文件都必須重新編譯。

4.  慎用內(nèi)聯(lián)

內(nèi)聯(lián)雖有它的好處,但是也要慎用,以下摘自《高質(zhì)量程序設(shè)計(jì)指南——C++/C語言》:

而在Google C++編碼規(guī)范中則規(guī)定得更加明確和詳細(xì):

內(nèi)聯(lián)函數(shù):

Tip: 只有當(dāng)函數(shù)只有 10 行甚至更少時(shí)才將其定義為內(nèi)聯(lián)函數(shù).

定義: 當(dāng)函數(shù)被聲明為內(nèi)聯(lián)函數(shù)之后, 編譯器會(huì)將其內(nèi)聯(lián)展開, 而不是按通常的函數(shù)調(diào)用機(jī)制進(jìn)行調(diào)用.
優(yōu)點(diǎn): 當(dāng)函數(shù)體比較小的時(shí)候, 內(nèi)聯(lián)該函數(shù)可以令目標(biāo)代碼更加高效. 對(duì)于存取函數(shù)以及其它函數(shù)體比較短, 性能關(guān)鍵的函數(shù), 鼓勵(lì)使用內(nèi)聯(lián).
缺點(diǎn): 濫用內(nèi)聯(lián)將導(dǎo)致程序變慢. 內(nèi)聯(lián)可能使目標(biāo)代碼量或增或減, 這取決于內(nèi)聯(lián)函數(shù)的大小. 內(nèi)聯(lián)非常短小的存取函數(shù)通常會(huì)減少代碼大小, 但內(nèi)聯(lián)一個(gè)相當(dāng)大的函數(shù)將戲劇性的增加代碼大小. 現(xiàn)代處理器由于更好的利用了指令緩存, 小巧的代碼往往執(zhí)行更快。
結(jié)論: 一個(gè)較為合理的經(jīng)驗(yàn)準(zhǔn)則是, 不要內(nèi)聯(lián)超過 10 行的函數(shù). 謹(jǐn)慎對(duì)待析構(gòu)函數(shù), 析構(gòu)函數(shù)往往比其表面看起來要更長(zhǎng), 因?yàn)橛须[含的成員和基類析構(gòu)函數(shù)被調(diào)用!
另一個(gè)實(shí)用的經(jīng)驗(yàn)準(zhǔn)則: 內(nèi)聯(lián)那些包含循環(huán)或 switch 語句的函數(shù)常常是得不償失 (除非在大多數(shù)情況下, 這些循環(huán)或 switch 語句從不被執(zhí)行).
有些函數(shù)即使聲明為內(nèi)聯(lián)的也不一定會(huì)被編譯器內(nèi)聯(lián), 這點(diǎn)很重要; 比如虛函數(shù)和遞歸函數(shù)就不會(huì)被正常內(nèi)聯(lián). 通常, 遞歸函數(shù)不應(yīng)該聲明成內(nèi)聯(lián)函數(shù).(遞歸調(diào)用堆棧的展開并不像循環(huán)那么簡(jiǎn)單, 比如遞歸層數(shù)在編譯時(shí)可能是未知的, 大多數(shù)編譯器都不支持內(nèi)聯(lián)遞歸函數(shù)). 虛函數(shù)內(nèi)聯(lián)的主要原因則是想把它的函數(shù)體放在類定義內(nèi), 為了圖個(gè)方便, 抑或是當(dāng)作文檔描述其行為, 比如精短的存取函數(shù).

-inl.h文件:


Tip: 復(fù)雜的內(nèi)聯(lián)函數(shù)的定義, 應(yīng)放在后綴名為 -inl.h 的頭文件中.


內(nèi)聯(lián)函數(shù)的定義必須放在頭文件中, 編譯器才能在調(diào)用點(diǎn)內(nèi)聯(lián)展開定義. 然而, 實(shí)現(xiàn)代碼理論上應(yīng)該放在 .cc 文件中, 我們不希望 .h 文件中有太多實(shí)現(xiàn)代碼, 除非在可讀性和性能上有明顯優(yōu)勢(shì).

如果內(nèi)聯(lián)函數(shù)的定義比較短小, 邏輯比較簡(jiǎn)單, 實(shí)現(xiàn)代碼放在 .h 文件里沒有任何問題. 比如, 存取函數(shù)的實(shí)現(xiàn)理所當(dāng)然都應(yīng)該放在類定義內(nèi). 出于編寫者和調(diào)用者的方便, 較復(fù)雜的內(nèi)聯(lián)函數(shù)也可以放到 .h 文件中, 如果你覺得這樣會(huì)使頭文件顯得笨重, 也可以把它萃取到單獨(dú)的 -inl.h 中. 這樣把實(shí)現(xiàn)和類定義分離開來, 當(dāng)需要時(shí)包含對(duì)應(yīng)的 -inl.h 即可。

本文參考書目:《C++ Primer》、《高質(zhì)量程序設(shè)計(jì)指南——C++/C語言》、Google C++編碼規(guī)范

相關(guān)文章

  • C語言中for循環(huán)問題(一個(gè)小坑需注意)

    C語言中for循環(huán)問題(一個(gè)小坑需注意)

    這篇文章主要給大家介紹了關(guān)于C語言中for循環(huán)問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C++樹之遍歷二叉樹實(shí)例詳解

    C++樹之遍歷二叉樹實(shí)例詳解

    這篇文章主要給大家介紹了關(guān)于C++樹之遍歷二叉樹的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C 語言條件運(yùn)算符詳細(xì)講解

    C 語言條件運(yùn)算符詳細(xì)講解

    本文主要介紹C語言中的條件運(yùn)算符,并提供示例代碼以便大家學(xué)習(xí)參考,希望能幫助學(xué)習(xí) C語言的同學(xué)
    2016-07-07
  • c語言重要的字符串與內(nèi)存函數(shù)

    c語言重要的字符串與內(nèi)存函數(shù)

    這篇文章主要介紹一些c語言中常用字符串函數(shù)和內(nèi)存函數(shù)的使用和注意事項(xiàng),并且為了幫助讀者理解和使用,也都模擬實(shí)現(xiàn)了他們的代碼,需要的朋友可以參考一下
    2021-09-09
  • 64位linux 編譯c提示gnu/stubs-32.h:No such file or directory的解決方法

    64位linux 編譯c提示gnu/stubs-32.h:No such file or directory的解決方法

    這篇文章主要介紹了64位linux 編譯c提示gnu/stubs-32.h:No such file or directory的解決方法,需要的朋友可以參考下
    2020-03-03
  • C語言由淺入深講解文件的操作上篇

    C語言由淺入深講解文件的操作上篇

    C語言具有操作文件的能力,比如打開文件、讀取和追加數(shù)據(jù)、插入和刪除數(shù)據(jù)、關(guān)閉文件、刪除文件等。與其他編程語言相比,C語言文件操作的接口相當(dāng)簡(jiǎn)單和易學(xué)
    2022-04-04
  • C語言中隨機(jī)數(shù)rand()函數(shù)詳解

    C語言中隨機(jī)數(shù)rand()函數(shù)詳解

    大家好,本篇文章主要講的是C語言中隨機(jī)數(shù)rand()函數(shù)詳解,感興趣的同學(xué)感快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • C語言詳細(xì)講解指針數(shù)組的用法

    C語言詳細(xì)講解指針數(shù)組的用法

    在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-05-05
  • vector list map 遍歷刪除制定元素 防止迭代器失效的實(shí)例

    vector list map 遍歷刪除制定元素 防止迭代器失效的實(shí)例

    下面小編就為大家?guī)硪黄獀ector list map 遍歷刪除制定元素 防止迭代器失效的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • C++模擬實(shí)現(xiàn)STL容器vector的示例代碼

    C++模擬實(shí)現(xiàn)STL容器vector的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C++如何模擬實(shí)現(xiàn)STL容器vector的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下
    2022-11-11

最新評(píng)論