麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > C > 正文

詳解內(nèi)聯(lián)函數(shù)與宏定義的區(qū)別

2020-02-24 14:25:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

內(nèi)聯(lián)函數(shù)可以加快程序的運(yùn)行速度,而內(nèi)聯(lián)函數(shù)也可以在編譯時(shí)直接嵌入到目標(biāo)代碼中,下面是武林技術(shù)頻道小編整理的詳解內(nèi)聯(lián)函數(shù)與宏定義的區(qū)別,一起跟著武林技術(shù)頻道小編的步伐來(lái)了解吧!

用內(nèi)聯(lián)取代宏:1.內(nèi)聯(lián)函數(shù)在運(yùn)行時(shí)可調(diào)試,而宏定義不可以;
2.編譯器會(huì)對(duì)內(nèi)聯(lián)函數(shù)的參數(shù)類(lèi)型做安全檢查或自動(dòng)類(lèi)型轉(zhuǎn)換(同普通函數(shù)),而宏定義則不會(huì);
3.內(nèi)聯(lián)函數(shù)可以訪問(wèn)類(lèi)的成員變量,宏定義則不能;
4.在類(lèi)中聲明同時(shí)定義的成員函數(shù),自動(dòng)轉(zhuǎn)化為內(nèi)聯(lián)函數(shù)。

文章(一)
內(nèi)聯(lián)函數(shù)與宏定義

  在C中,常用預(yù)處理語(yǔ)句#define來(lái)代替一個(gè)函數(shù)定義。例如:
    #define MAX(a,b) ((a)>(b)?(a):(b))
  該語(yǔ)句使得程序中每個(gè)出現(xiàn)MAX(a,b)函數(shù)調(diào)用的地方都被宏定義中后面的表達(dá)式((a)>(b)?(a):(b))所替換。
  宏定義語(yǔ)句的書(shū)寫(xiě)格式有過(guò)分的講究, MAX與括號(hào)之間不能有空格,所有的參數(shù)都要
  放在括號(hào)里。盡管如此,它還是有麻煩:
    int a=1,b=0;
    MAX(a++,b); //a被增值2次
    MAX(a++,b+10); //a被增值1次
    MAX(a,"Hello"); //錯(cuò)誤地比較int和字符串,沒(méi)有參數(shù)類(lèi)型檢查
    MAX( )函數(shù)的求值會(huì)由于兩個(gè)參數(shù)值的大小不同而產(chǎn)生不同的副作用。
    MAX(a++,b)的值為2,同時(shí)a的值為3;
    MAX(a++,b+10)的值為10,同時(shí)a的值為2。
  如果是普通函數(shù),則MAX(a,"HellO")會(huì)受到函數(shù)調(diào)用的檢查,但此處不會(huì)因?yàn)閮蓚€(gè)參數(shù)類(lèi)型不同而被編譯拒之門(mén)外。幸運(yùn)的是,通過(guò)一個(gè)內(nèi)聯(lián)函數(shù)可以得到所有宏的替換效能和 所有可預(yù)見(jiàn)的狀態(tài)以及常規(guī)函數(shù)的類(lèi)型檢查:
    inline int MAX(int a,int b)
    {
     return a>b?a:b;
    }
1.內(nèi)聯(lián)函數(shù)與宏的區(qū)別:
????? 傳統(tǒng)的宏定義函數(shù)可能會(huì)引起一些麻煩。
????? ex:
?????????? #define F(x) x+x
?????????? void main(){int i=1;F(i++);}
??????????? 這里x將被加兩次。
??????? 內(nèi)聯(lián)函數(shù)被編譯器自動(dòng)的用函數(shù)的形勢(shì)添加進(jìn)代碼,而不會(huì)出現(xiàn)這種情況。
??????? 內(nèi)聯(lián)函數(shù)的使用提高了效率(省去了很多函數(shù)調(diào)用匯編代碼如:call和ret等)。
2.內(nèi)聯(lián)函數(shù)的使用:
???????? 所有在類(lèi)的聲明中定義的函數(shù)將被自動(dòng)認(rèn)為是內(nèi)聯(lián)函數(shù)。
??????? class A()
?????? {
???????????? void c();// not a inline function;
??????????? void d(){ print("d() is a inline function.");}
??????? }
??????? 如果想將一個(gè)全局函數(shù)定義為內(nèi)聯(lián)函數(shù)可用,inline 關(guān)鍵字。
??????? inline a(){print("a() is a inline function.");}
注意:
????? 在內(nèi)聯(lián)函數(shù)中如果有復(fù)雜操作將不被內(nèi)聯(lián)。如:循環(huán)和遞歸調(diào)用。
總結(jié):
????? 將簡(jiǎn)單短小的函數(shù)定義為內(nèi)聯(lián)函數(shù)將會(huì)提高效率。

文章(二)
8.5.1 用內(nèi)聯(lián)取代宏代碼

C++ 語(yǔ)言支持函數(shù)內(nèi)聯(lián),其目的是為了提高函數(shù)的執(zhí)行效率(速度)。
在 C程序中,可以用宏代碼提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來(lái)象函數(shù)。預(yù)處理器用復(fù)制宏代碼的方式代替函數(shù)調(diào)用,省去了參數(shù)壓棧、生成匯編語(yǔ)言的 CALL調(diào)用、返回參數(shù)、執(zhí)行return等過(guò)程,從而提高了速度。使用宏代碼最大的缺點(diǎn)是容易出錯(cuò),預(yù)處理器在復(fù)制宏代碼時(shí)常常產(chǎn)生意想不到的邊際效應(yīng)。例如
#define MAX(a, b)?????? (a) > (b) ? (a) : (b)
語(yǔ)句?
result = MAX(i, j) + 2 ;
將被預(yù)處理器解釋為
result = (i) > (j) ? (i) : (j) + 2 ;
由于運(yùn)算符‘+'比運(yùn)算符‘:'的優(yōu)先級(jí)高,所以上述語(yǔ)句并不等價(jià)于期望的
result = ( (i) > (j) ? (i) : (j) ) + 2 ;
如果把宏代碼改寫(xiě)為
#define MAX(a, b)?????? ( (a) > (b) ? (a) : (b) )
則可以解決由優(yōu)先級(jí)引起的錯(cuò)誤。但是即使使用修改后的宏代碼也不是萬(wàn)無(wú)一失的,例如語(yǔ)句
result = MAX(i++, j);
將被預(yù)處理器解釋為
result = (i++) > (j) ? (i++) : (j);
對(duì)于C++ 而言,使用宏代碼還有另一種缺點(diǎn):無(wú)法操作類(lèi)的私有數(shù)據(jù)成員。
讓我們看看C++ 的“函數(shù)內(nèi)聯(lián)”是如何工作的。對(duì)于任何內(nèi)聯(lián)函數(shù),編譯器在符號(hào)表里放入函數(shù)的聲明(包括名字、參數(shù)類(lèi)型、返回值類(lèi)型)。如果編譯器沒(méi)有發(fā)現(xiàn)內(nèi)聯(lián)函數(shù)存在錯(cuò)誤,那么該函數(shù)的代碼也被放入符號(hào)表里。在調(diào)用一個(gè)內(nèi)聯(lián)函數(shù)時(shí),編譯器首先檢查調(diào)用是否正確(進(jìn)行類(lèi)型安全檢查,或者進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換,當(dāng)然對(duì)所有的函數(shù)都一樣)。如果正確,內(nèi)聯(lián)函數(shù)的代碼就會(huì)直接替換函數(shù)調(diào)用,于是省去了函數(shù)調(diào)用的開(kāi)銷(xiāo)。這個(gè)過(guò)程與預(yù)處理有顯著的不同,因?yàn)轭A(yù)處理器不能進(jìn)行類(lèi)型安全檢查,或者進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換。假如內(nèi)聯(lián)函數(shù)是成員函數(shù),對(duì)象的地址(this)會(huì)被放在合適的地方,這也是預(yù)處理器辦不到的。
C++ 語(yǔ)言的函數(shù)內(nèi)聯(lián)機(jī)制既具備宏代碼的效率,又增加了安全性,而且可以自由操作類(lèi)的數(shù)據(jù)成員。所以在C++ 程序中,應(yīng)該用內(nèi)聯(lián)函數(shù)取代所有宏代碼,“斷言assert”恐怕是唯一的例外。assert是僅在Debug版本起作用的宏,它用于檢查“不應(yīng)該”發(fā)生的情況。為了不在程序的Debug版本和Release版本引起差別,assert不應(yīng)該產(chǎn)生任何副作用。如果assert是函數(shù),由于函數(shù)調(diào)用會(huì)引起內(nèi)存、代碼的變動(dòng),那么將導(dǎo)致Debug版本與Release版本存在差異。所以assert不是函數(shù),而是宏。(參見(jiàn)6.5節(jié)“使用斷言”)
8.5.2 內(nèi)聯(lián)函數(shù)的編程風(fēng)格
關(guān)鍵字inline必須與函數(shù)定義體放在一起才能使函數(shù)成為內(nèi)聯(lián),僅將inline放在函數(shù)聲明前面不起任何作用。如下風(fēng)格的函數(shù)Foo不能成為內(nèi)聯(lián)函數(shù):
inline void Foo(int x, int y);? // inline僅與函數(shù)聲明放在一起
void Foo(int x, int y)
{

}
而如下風(fēng)格的函數(shù)Foo則成為內(nèi)聯(lián)函數(shù):
void Foo(int x, int y);?
inline void Foo(int x, int y) // inline與函數(shù)定義體放在一起
{

}
所以說(shuō),inline是一種“用于實(shí)現(xiàn)的關(guān)鍵字”,而不是一種“用于聲明的關(guān)鍵字”。一般地,用戶(hù)可以閱讀函數(shù)的聲明,但是看不到函數(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è)基本原則:聲明與定義不可混為一談,用戶(hù)沒(méi)有必要、也不應(yīng)該知道函數(shù)是否需要內(nèi)聯(lián)。
定義在類(lèi)聲明之中的成員函數(shù)將自動(dòng)地成為內(nèi)聯(lián)函數(shù),例如
class A
{
public:
void Foo(int x, int y) { … }? // 自動(dòng)地成為內(nèi)聯(lián)函數(shù)
}
將成員函數(shù)的定義體放在類(lèi)聲明之中雖然能帶來(lái)書(shū)寫(xiě)上的方便,但不是一種良好的編程風(fēng)格,上例應(yīng)該改成:
// 頭文件
class A
{
public:
void Foo(int x, int y);?
}
// 定義文件
inline void A::Foo(int x, int y)
{

}
8.5.3 慎用內(nèi)聯(lián)
內(nèi)聯(lián)能提高函數(shù)的執(zhí)行效率,為什么不把所有的函數(shù)都定義成內(nèi)聯(lián)函數(shù)?
如果所有的函數(shù)都是內(nèi)聯(lián)函數(shù),還用得著“內(nèi)聯(lián)”這個(gè)關(guān)鍵字嗎?
內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價(jià),僅僅省去了函數(shù)調(diào)用的開(kāi)銷(xiāo),從而提高函數(shù)的執(zhí)行效率。如果執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間,相比于函數(shù)調(diào)用的開(kāi)銷(xiāo)較大,那么效率的收獲會(huì)很少。另一方面,每一處內(nèi)聯(lián)函數(shù)的調(diào)用都要復(fù)制代碼,將使程序的總代碼量增大,消耗更多的內(nèi)存空間。以下情況不宜使用內(nèi)聯(lián):
(1)如果函數(shù)體內(nèi)的代碼比較長(zhǎng),使用內(nèi)聯(lián)將導(dǎo)致內(nèi)存消耗代價(jià)較高。
(2)如果函數(shù)體內(nèi)出現(xiàn)循環(huán),那么執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間要比函數(shù)調(diào)用的開(kāi)銷(xiāo)大。

類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)容易讓人誤解成使用內(nèi)聯(lián)更有效。要當(dāng)心構(gòu)造函數(shù)和析構(gòu)函數(shù)可能會(huì)隱藏一些行為,如“偷偷地”執(zhí)行了基類(lèi)或成員對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù)。所以不要隨便地將構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義體放在類(lèi)聲明中。
一個(gè)好的編譯器將會(huì)根據(jù)函數(shù)的定義體,自動(dòng)地取消不值得的內(nèi)聯(lián)(這進(jìn)一步說(shuō)明了inline不應(yīng)該出現(xiàn)在函數(shù)的聲明中)。
8.6 一些心得體會(huì)
C++ 語(yǔ)言中的重載、內(nèi)聯(lián)、缺省參數(shù)、隱式轉(zhuǎn)換等機(jī)制展現(xiàn)了很多優(yōu)點(diǎn),但是這些優(yōu)點(diǎn)的背后都隱藏著一些隱患。正如人們的飲食,少食和暴食都不可取,應(yīng)當(dāng)恰到好處。我們要辨證地看待C++的新機(jī)制,應(yīng)該恰如其分地使用它們。雖然這會(huì)使我們編程時(shí)多費(fèi)一些心思,少了一些痛快,但這才是編程的藝術(shù)。
第9章 類(lèi)的構(gòu)造函數(shù)、析構(gòu)函數(shù)與賦值函數(shù)
構(gòu)造函數(shù)、析構(gòu)函數(shù)與賦值函數(shù)是每個(gè)類(lèi)最基本的函數(shù)。它們太普通以致讓人容易麻痹大意,其實(shí)這些貌似簡(jiǎn)單的函數(shù)就象沒(méi)有頂蓋的下水道那樣危險(xiǎn)。
每個(gè)類(lèi)只有一個(gè)析構(gòu)函數(shù)和一個(gè)賦值函數(shù),但可以有多個(gè)構(gòu)造函數(shù)(包含一個(gè)拷貝構(gòu)造函數(shù),其它的稱(chēng)為普通構(gòu)造函數(shù))。對(duì)于任意一個(gè)類(lèi)A,如果不想編寫(xiě)上述函數(shù),C++編譯器將自動(dòng)為A產(chǎn)生四個(gè)缺省的函數(shù),如
A(void); // 缺省的無(wú)參數(shù)構(gòu)造函數(shù)
A(const A &a); // 缺省的拷貝構(gòu)造函數(shù)
~A(void); // 缺省的析構(gòu)函數(shù)
A & operate =(const A &a); // 缺省的賦值函數(shù)
這不禁讓人疑惑,既然能自動(dòng)生成函數(shù),為什么還要程序員編寫(xiě)?
原因如下:
(1)如果使用“缺省的無(wú)參數(shù)構(gòu)造函數(shù)”和“缺省的析構(gòu)函數(shù)”,等于放棄了自主“初始化”和“清除”的機(jī)會(huì),C++發(fā)明人Stroustrup的好心好意白費(fèi)了。
(2)“缺省的拷貝構(gòu)造函數(shù)”和“缺省的賦值函數(shù)”均采用“位拷貝”而非“值拷貝”的方式來(lái)實(shí)現(xiàn),倘若類(lèi)中含有指針變量,這兩個(gè)函數(shù)注定將出錯(cuò)。

對(duì)于那些沒(méi)有吃夠苦頭的C++程序員,如果他說(shuō)編寫(xiě)構(gòu)造函數(shù)、析構(gòu)函數(shù)與賦值函數(shù)很容易,可以不用動(dòng)腦筋,表明他的認(rèn)識(shí)還比較膚淺,水平有待于提高。
本章以類(lèi)String的設(shè)計(jì)與實(shí)現(xiàn)為例,深入闡述被很多教科書(shū)忽視了的道理。String的結(jié)構(gòu)如下:
class String
{
? public:
String(const char *str = NULL); // 普通構(gòu)造函數(shù)
String(const String &other); // 拷貝構(gòu)造函數(shù)
~ String(void); // 析構(gòu)函數(shù)
String & operate =(const String &other); // 賦值函數(shù)
? private:
char?? *m_data; // 用于保存字符串
};
======================================================================================================
在程序編譯時(shí),編譯器將程序中出現(xiàn)的內(nèi)聯(lián)函數(shù)的調(diào)用表達(dá)式用內(nèi)聯(lián)函數(shù)的函數(shù)體來(lái)進(jìn)行替換。顯然,這種做法不會(huì)產(chǎn)生轉(zhuǎn)去轉(zhuǎn)回的問(wèn)題,但是由于在編譯時(shí)將函數(shù)休中的代碼被替代到程序中,因此會(huì)增加目標(biāo)程序代碼量,進(jìn)而增加空間開(kāi)銷(xiāo),而在時(shí)間代銷(xiāo)上不象函數(shù)調(diào)用時(shí)那么大,可見(jiàn)它是以目標(biāo)代碼的增加為代價(jià)來(lái)?yè)Q取時(shí)間的節(jié)省。

上述是武林技術(shù)頻道小編為大家?guī)?lái)的詳解內(nèi)聯(lián)函數(shù)與宏定義的區(qū)別,希望大家學(xué)習(xí)完這些知識(shí)有一定的啟發(fā),也希望大家能收藏本站,方便查閱。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 91重口视频 | 在线亚洲欧美 | 久久久久久久久久亚洲 | av在线更新| 免费人成年短视频在线观看网站 | 91麻豆精品国产91久久久点播时间 | 免费观看高清视频网站 | 成人不卡免费视频 | 草久免费 | 国产一区二区三区四区在线 | 成人午夜激情网 | 羞羞的动漫在线观看 | 久久99精品久久久久久青青日本 | 成人精品aaaa网站 | 亚洲精品成人18久久久久 | 日本黄色不卡视频 | 日产精品久久久一区二区福利 | 成人毛片100免费观看 | 性欧美极品xxxx欧美一区二区 | 久草在线观看福利视频 | 国产免费午夜 | 黄视频网站免费在线观看 | 国产精品三级a三级三级午夜 | 斗破苍穹在线免费 | 激情宗合| 深夜激情视频 | 欧美精品一区二区视频 | 中文字幕四区 | 国产精品久久久久久久久久大牛 | 91看片免费版 | 国产精品av久久久久久久久久 | 成片免费观看视频大全 | 日日碰日日操 | 又黄又爽免费无遮挡在线观看 | 午夜国内精品a一区二区桃色 | 亚洲成人免费电影 | 农村少妇吞精夜夜爽视频 | 精品一区二区免费视频视频 | 免费一级电影 | 美国黄色毛片女人性生活片 | 91成人免费 |