網站首頁 編程語言 正文
內聯函數的概念
以inline
修飾的函數叫做內聯函數,編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數壓棧的開銷,內聯函數的使用可以提升程序的運行效率。
舉個例子:
在C++中我們通常定義以下函數來求兩個整數的最大值:
代碼如下:
int max(int a, int b) { return a > b ? a : b; }
為這么一個小的操作定義一個函數的好處有:
- 閱讀和理解函數 max 的調用,要比讀一條等價的條件表達式并解釋它的含義要容易得多
- 如果需要做任何修改,修改函數要比找出并修改每一處等價表達式容易得多
- 使用函數可以確保統一的行為,每個測試都保證以相同的方式實現
- 函數可以重用,不必為其他應用程序重寫代碼
雖然有這么多好處,但是寫成函數有一個潛在的缺點:調用函數比求解等價表達式要慢得多。在大多數的機器上,調用函數都要做很多工作:
- 程序需要存儲當前地址,以便調用結束后返回繼續執行 - 程序將傳入函數的參數壓棧 - 程序跳到跳到標記函數起點的內存單元,執行函數代碼 - 函數調用結束后,將棧清空,返回到之前存儲的地址繼續執行
C++中支持內聯函數
,其目的是為了提高函數的執行效率,用關鍵字 inline 放在函數定義(注意是定義而非聲明)的前面即可將函數指定為內聯函數,內聯函數通常就是將它在程序中的每個調用點上“內聯地”展開,相當于直接copy一份函數體內代碼,在執行到的時候直接按照代碼順序執行,省去了許多函數調用過程,節省了時間。
假設我們將 max 定義為內聯函數:
代碼如下:
inline int max(int a, int b) { return a > b ? a : b; }
則調用: cout<<max(a, b)<<endl; 在編譯時展開為: cout<<(a > b ? a : b)<<endl;
從而消除了把 max寫成函數的額外執行開銷
是不是覺得這和宏有些像?那為什么不直接用宏?還要整個內聯函數
內聯函數和宏
首先,宏能夠表達的意思有限,通常是一行的表達式。其次,用宏的安全性不高,容易出錯。
假設定義宏如下:
#define MAX(a,b) a>b?:a:b
那么語句
res = MAX(i,j)+2;
會被預處理器擴展為
res = i > j? i:j+2;
由于+的優先級高于?,因此最終比較結果與我們期望不符。
那如果把宏修改為
#define MAX(a,b) (i > j? i:j)
仍然存在問題,例如
res = MAX(i++,j) res = (i++ < j? i++:j); // i被+了兩次
同時,宏無法調試,但內聯函數可以。在程序的調試版本,內聯函數并沒有真正內聯,就像普通函數一樣實現調試,在程序的發行版本,編譯器才會實現真正內聯。
無論是《Effective C++》中的 “Prefer consts,enums,and inlines to #defines” 條款,還是《高質量程序設計指南——C++/C語言》中的“用函數內聯取代宏”,宏在C++中基本是被廢了。
內聯函數的特性
1、inline是一種以空間換時間的做法,省了去調用函數的額外開銷。由于內聯函數會在調用的位置展開,所以代碼很長或者有遞歸的函數不適宜作為內聯函數。頻繁調用的小函數建議定義成內聯函數。
2、inline對于編譯器而言只是一個建議,編譯器會自動優化,如果定義為inline的函數體內有遞歸等,編譯器優化時會忽略掉內聯。
3、inline不建議聲明和定義分離
,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址了鏈接就會找不到。
4、關鍵字 inline 必須與函數定義體放在一起才能使函數成為內聯,僅將 inline 放在函數聲明前面不起任何作用。
5 .相比于宏,有類型檢查,安全性更高,具有一般函數特性,可調試。
總結
原文鏈接:https://blog.csdn.net/weixin_53306029/article/details/122355460
相關推薦
- 2023-04-06 C++中的多態問題—理解虛函數表及多態實現原理_C 語言
- 2022-05-27 一起來看看python的裝飾器代碼_python
- 2023-12-18 Path環境變量點編輯無法展開
- 2022-06-16 golang?gorm更新日志執行SQL示例詳解_Golang
- 2022-05-21 python?判斷文件或文件夾是否存在_python
- 2022-07-12 BlockingQueue阻塞隊列原理以及實現
- 2023-01-19 GO語言的控制語句詳解包括GO語言的指針語法_Golang
- 2022-10-04 R語言將變量分組的3種方法實例(含cut函數說明)_R語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支