亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

詳解內聯函數與宏定義的區別

2020-02-24 14:25:59
字體:
來源:轉載
供稿:網友

內聯函數可以加快程序的運行速度,而內聯函數也可以在編譯時直接嵌入到目標代碼中,下面是武林技術頻道小編整理的詳解內聯函數與宏定義的區別,一起跟著武林技術頻道小編的步伐來了解吧!

用內聯取代宏:1.內聯函數在運行時可調試,而宏定義不可以;
2.編譯器會對內聯函數的參數類型做安全檢查或自動類型轉換(同普通函數),而宏定義則不會;
3.內聯函數可以訪問類的成員變量,宏定義則不能;
4.在類中聲明同時定義的成員函數,自動轉化為內聯函數。

文章(一)
內聯函數與宏定義

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

文章(二)
8.5.1 用內聯取代宏代碼

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

}
而如下風格的函數Foo則成為內聯函數:
void Foo(int x, int y);?
inline void Foo(int x, int y) // inline與函數定義體放在一起
{

}
所以說,inline是一種“用于實現的關鍵字”,而不是一種“用于聲明的關鍵字”。一般地,用戶可以閱讀函數的聲明,但是看不到函數的定義。盡管在大多數教科書中內聯函數的聲明、定義體前面都加了inline關鍵字,但我認為inline不應該出現在函數的聲明中。這個細節雖然不會影響函數的功能,但是體現了高質量C++/C程序設計風格的一個基本原則:聲明與定義不可混為一談,用戶沒有必要、也不應該知道函數是否需要內聯。
定義在類聲明之中的成員函數將自動地成為內聯函數,例如
class A
{
public:
void Foo(int x, int y) { … }? // 自動地成為內聯函數
}
將成員函數的定義體放在類聲明之中雖然能帶來書寫上的方便,但不是一種良好的編程風格,上例應該改成:
// 頭文件
class A
{
public:
void Foo(int x, int y);?
}
// 定義文件
inline void A::Foo(int x, int y)
{

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

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

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

上述是武林技術頻道小編為大家帶來的詳解內聯函數與宏定義的區別,希望大家學習完這些知識有一定的啟發,也希望大家能收藏本站,方便查閱。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
另类天堂视频在线观看| 亚洲а∨天堂久久精品喷水| 91在线观看免费网站| 欧美激情综合色综合啪啪五月| 亚洲黄色片网站| 国产综合香蕉五月婷在线| 亚洲欧美日韩一区二区三区在线| 亚洲free性xxxx护士hd| 日韩亚洲第一页| 中文字幕自拍vr一区二区三区| 精品中文字幕在线| 欧美专区在线视频| 亚洲国产欧美精品| 国产精品精品一区二区三区午夜版| 欧美日韩亚洲国产一区| 亚洲成人av在线播放| 精品露脸国产偷人在视频| 黄网动漫久久久| 欧美日韩国产123| 久久久精品久久久久| 国产美女搞久久| 国产精品7m视频| 成人444kkkk在线观看| 性夜试看影院91社区| 欧美日韩一区二区免费视频| 精品视频在线观看日韩| 尤物九九久久国产精品的特点| 亚洲女同精品视频| 少妇精69xxtheporn| 色悠悠久久88| 亚洲free性xxxx护士hd| 日韩视频永久免费观看| 日韩精品在线观看一区| 亚洲国产成人av在线| 日韩人体视频一二区| 久久久久久国产精品久久| 一区二区欧美久久| 欧美激情国产精品| 欧美激情中文字幕在线| 久久亚洲精品中文字幕冲田杏梨| 一区二区欧美在线| 色妞欧美日韩在线| 国产精品∨欧美精品v日韩精品| 一区二区三区回区在观看免费视频| 日韩视频免费观看| 7777免费精品视频| 亚洲精品欧美日韩专区| www国产亚洲精品久久网站| 一本一本久久a久久精品综合小说| 国模gogo一区二区大胆私拍| 欧美综合国产精品久久丁香| 欧美成人午夜免费视在线看片| 4438全国成人免费| 国产日产欧美a一级在线| 亚洲黄色av女优在线观看| 在线播放亚洲激情| 国产精品美女www爽爽爽视频| 欧美第一黄色网| 国产精品入口免费视频一| 91沈先生作品| 亚洲欧美日韩爽爽影院| 欧美日韩福利在线观看| 久久99精品视频一区97| 成人美女av在线直播| 亚洲国产日韩欧美在线图片| 欧美特级www| 丝袜美腿精品国产二区| 亚洲色图国产精品| 九九热精品视频| 欧美wwwwww| 国产精品女人网站| 91久久精品国产91久久| 97香蕉久久夜色精品国产| 亚洲高清色综合| 国模吧一区二区| 亚洲精品免费av| 久久99精品久久久久久青青91| 国产精品美女在线| 91精品国产777在线观看| 最新69国产成人精品视频免费| 亚洲毛片在线免费观看| 91免费人成网站在线观看18| 在线看片第一页欧美| 国产精品88a∨| 福利视频导航一区| 日韩免费观看视频| 国产一区二区三区在线看| 欧美丝袜一区二区三区| 午夜精品久久久久久99热软件| 成人午夜一级二级三级| 日韩精品视频在线观看免费| 日日摸夜夜添一区| 精品国产一区二区三区久久久狼| 精品国内亚洲在观看18黄| 精品久久中文字幕久久av| 精品欧美激情精品一区| 欧美天天综合色影久久精品| 欧美视频裸体精品| 国产一区红桃视频| 欧美壮男野外gaytube| 国产欧美精品一区二区三区介绍| 亚洲女人天堂成人av在线| 欧美大片va欧美在线播放| 亚洲精品美女在线观看播放| 久久久久www| 国产美女被下药99| 亚洲欧洲在线视频| 欧美一区二区三区图| 在线观看国产精品淫| 欧美日韩成人在线视频| 欧美日本亚洲视频| 欧美激情网友自拍| 日韩中文字幕在线视频播放| 亚洲一区二区三区xxx视频| 国产精品999999| 亚洲性视频网址| 97福利一区二区| 亚洲国产精彩中文乱码av| 26uuu另类亚洲欧美日本一| 俺去亚洲欧洲欧美日韩| 久久成人精品视频| 国产精品91久久久久久| 欧美精品日韩www.p站| 高清一区二区三区四区五区| 色七七影院综合| 国产精品人成电影| 欧美日韩中文字幕在线视频| 亚洲国产成人久久综合一区| 日韩小视频在线观看| 日韩中文字幕欧美| 中文字幕日韩欧美精品在线观看| 国产欧美日韩精品在线观看| 欧美成人精品一区二区三区| 国产精品久久电影观看| 欧美激情一区二区三区高清视频| 国产精品久久一区主播| 亚洲欧美综合精品久久成人| 最近日韩中文字幕中文| 国产国产精品人在线视| 亚洲国产成人爱av在线播放| 中文字幕在线成人| 国产精品高潮呻吟久久av无限| 欧美一区二区三区免费视| 亚洲午夜精品久久久久久久久久久久| 国内精品小视频在线观看| 欧美激情一区二区三区高清视频| 久久躁狠狠躁夜夜爽| 国产视频精品一区二区三区| 亚洲欧美精品中文字幕在线| 蜜臀久久99精品久久久久久宅男| 亚洲精美色品网站| 91日韩在线播放| 亚州国产精品久久久| 亚洲自拍偷拍网址| 中文国产成人精品久久一| 国产一区二区黑人欧美xxxx| 97超碰色婷婷| 欧美成人精品三级在线观看| 亚洲aⅴ男人的天堂在线观看| 91精品国产综合久久香蕉的用户体验| 欧美日韩一区二区三区在线免费观看| 成人高清视频观看www| 97在线免费视频| 88xx成人精品|