深入理解 C++ inline:三大語法特性 + 七大高頻考點全解析

一、什么是內聯函數

  • 編譯器嘗試將 inline 函數的代碼直接插入調用處(類似宏展開),避免函數調用的壓棧、跳轉、返回等額外開銷。
  • 適用于短小頻繁調用的函數:如簡單的 getter/setter、數學運算等。
  • inline 只是 建議,編譯器可能忽略(如函數太復雜或遞歸)。內聯展開是以空間換時間,過度使用會導致代碼膨脹(code bloat)。
inline int add(int a, int b) {return a + b;
}int main() {int result = add(3, 5);  // 可能被替換為 `int result = 3 + 5;`return 0;
}

在這里插入圖片描述
可以看出,內聯函數少了函數壓棧,出棧,調用的過程,所以可以節約傳參時間,但是也會導致代碼膨脹

二、類內定義的成員函數默認是 inline

在類內部直接定義的成員函數(非顯式聲明)隱式內聯

class MyClass {
public:int getValue() {  // 隱式 inlinereturn value;}
private:int value;
};

上述代碼等價于:

class MyClass {
public:inline int getValue() {  // 隱式 inlinereturn value;}
private:int value;
};

但是具體的行為還是取決于編譯器。即使不內聯,也會為其生成鏈接符號(在有虛函數、虛表機制時更復雜)。

三、C++17 引入的 inline 變量

C++17 允許在頭文件中定義 inline 變量,避免多次定義錯誤。在C++17之前如果在頭文件中直接定義(非聲明)一個全局變量,且該頭文件被多個源文件(.cpp)包含,會導致同一個變量被多次定義(ODR,One Definition Rule),鏈接時會報錯。

3.1、這么寫是錯誤的

global.h

int num = 10;

如果多個 .cpp 文件包含此頭文件會導致重復定義問題。

3.2、傳統解決方案

使用 extern 聲明(推薦方式),將全局變量定義在一個 .cpp 文件中,在 .h 頭文件中用 extern 申明這個變量。

global.h

extern int num;

global.cpp

int num = 10;

3.3、C++17 引入 inline 解決了這個問題

global.h

inline int num = 10;

如果多個 .cpp 文件包含此頭文件也不會導致重復定義問題。

四、常考點

4.1、inline 和宏的區別

特性inline 函數宏 (#define)
類型檢查? 支持編譯時類型檢查? 不支持
編譯調試支持? 可調試(保留函數信息)? 難以調試,報錯不明確
安全性? 參數求值安全? 多次求值可能副作用
作用域? 遵循 C++ 命名空間規則? 全局替換
語義清晰度? 強? 易錯

4.2、C++17 中 inline 關鍵字添加了什么新的特性

C++17 引入 inline 變量,允許在頭文件中定義變量而不會造成鏈接錯誤(類似函數)。

4.3、inline 有什么副作用

  • 可能增加可執行文件大小;
  • 濫用會降低指令緩存命中率;

4.4、inline 可以修飾虛函數嘛

不可以,inline 是直接在調用處展開,但是動態多態無法獲知當前調用的究竟是哪個函數,需要根據傳入的引用或者指針去判斷,這本質上就是沖突的。

但是!但是!但是!作者這里試了一下,可以修飾的,編譯可以通過,因為 inline 只是建議,編譯器不采用就好了。

4.5、inline 可以修飾構造函數嘛

可以,構造函數是普通成員函數的一種,完全可以被 inline 修飾,而且在類內定義的構造函數也默認是隱式 inline 的

class MyClass {
public:// 隱式 inline 構造函數MyClass(int x) : value(x) {}// 或顯式 inlineinline MyClass(double x) : value(static_cast<int>(x)) {}private:int value;
};

4.6、inline 可以修飾析構函數嘛

析構函數(包括虛析構函數)也是特殊的成員函數,也可以用 inline 修飾

但是和 inline 可以修飾虛函數嘛 這個問題一樣,inline 只是建議罷了。

4.7、內聯函數可不可以遞歸展開

內聯函數在語法上可以遞歸,但在實現上一般不會被遞歸地內聯展開。除非遞歸深度在編譯期是靜態可知的(如模板遞歸)。

下面的代碼不會報錯:

inline int factorial(int n) {return (n <= 1) ? 1 : n * factorial(n - 1);
}

inline 和遞歸并不沖突,但是這種不知道遞歸深度的代碼是很危險的,所以編譯器可能部分展開,也可能一點都不展開。

下面的代碼直接在編譯器確定了遞歸深度,所以可能完全展開

template<int N>
inline int factorial() {return N * factorial<N - 1>();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85176.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85176.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85176.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flink 與 Hive 深度集成

引言 在大數據生態中&#xff0c;Flink 的流批一體化處理能力與 Hive 的數據存儲分析優勢結合&#xff0c;通過 Flink Connector for Hive 實現無縫對接&#xff0c;能顯著提升數據處理效率。本文將系統解析 Flink 與 Hive 集成的核心操作&#xff0c;涵蓋配置、讀寫、優化全流…

Axios面試常見問題詳解

axios面試常問題目及其詳解 以下是前端面試中關于 Axios 的常見問題及詳細解答&#xff0c;涵蓋核心原理、實戰場景和進階優化&#xff0c;幫助你在面試中清晰展示技術深度。 1. Axios 是什么&#xff1f;它與原生 Fetch API 有何區別&#xff1f; 回答要點&#xff1a; Axi…

14.2 《3小時從零搭建企業級LLaMA3語言助手:GitHub配置+私有化模型集成全實戰》

3小時從零搭建企業級LLaMA3語言助手&#xff1a;GitHub配置私有化模型集成全實戰 關鍵詞&#xff1a;GitHub 倉庫配置, 項目初始化, 目錄結構設計, 私有化模型集成, 開發環境標準化 Fork 并配置 GitHub 項目倉庫 本節將手把手完成 LanguageMentor 項目的倉庫克隆、環境配置和…

生物制藥自動化升級:Modbus TCP與Ethernet/IP協議轉換實踐

為優化生物制藥生產流程&#xff0c;我司計劃將現有的Allen-Bradley PLC控制系統與新型生物反應器進行集成。由于兩者采用不同的通信協議&#xff08;AB PLC使用Modbus TCP&#xff0c;而生物反應器支持Ethernet/IP&#xff09;&#xff0c;直接通信存在障礙。為此通過穩聯技術…

商業云手機核心優缺點分析

商業云手機核心優缺點分析&#xff0c;綜合技術性能、成本效率及場景適配性等多維度對比&#xff1a; 核心優勢? 成本革命? 硬件零投入?&#xff1a;免除實體手機采購&#xff08;旗艦機均價6000元&#xff09;&#xff0c;企業百臺規模可省60萬 CAPEX。 彈性計費?&…

Windows 遠程桌面添加 SSL 證書指南

Windows 遠程桌面添加 SSL 證書指南 &#x1f9fe; 準備工作&#x1f510; 第一步&#xff1a;使用 Certbot 申請 SSL 證書&#x1f4e6; 第二步&#xff1a;生成 PFX 格式證書文件&#x1f4c1; 第三步&#xff1a;導入證書到 Windows 證書管理器&#x1f512; 第四步&#xf…

項目實訓技術實現——核心關鍵:基于二叉分割的布局生成算法

核心關鍵&#xff1a;基于二叉分割的布局生成算法 上一篇針對llava這種為每個元素分別預測每個元素的框的方法進行了分析&#xff0c;已經證實這條路難以行得通。因此&#xff0c;我們考慮直接按照板塊劃分整個背景布局&#xff0c;然后在板塊內&#xff0c;進一步劃分出我們需…

uniapp 配置devserver代理

在uniapp項目中配置devserver代理&#xff0c;需要先檢查用的vue版本。 vue3不能在manifest.json配置代理。 1.先檢查項目用的vue版本 找到manifest.json文件查看vue的版本。 2.vue2在manifest.json內配置 "h5" : { "devServer": { …

移動端 WebView 頁面性能調試實戰:WebDebugX等工具協同與優化

隨著移動互聯網的發展&#xff0c;越來越多的應用開始使用 WebView 加載網頁內容。然而&#xff0c;這種方式雖然能快速實現跨平臺開發&#xff0c;但也帶來了很多性能瓶頸&#xff0c;尤其是在移動端設備上。WebView 本身的性能限制、頁面加載慢、JS 執行阻塞等問題時常成為開…

臨時文件夾大量0字節xml問題排查

某天偶然打開我的c:\users\我的用戶名\AppData\Local\Temp 目錄&#xff0c;發現有很多0字節的.xml文件&#xff0c;你刪除以后一會還會大量產生&#xff0c;如下圖&#xff1a; 下載了ProcessMonitor&#xff0c;記錄了一會日志&#xff0c;查找*.xml發現是資源管理器在創建這…

突破微小目標檢測瓶頸:智能無人機在藍莓產量估算中的解決方案

【導讀】 本文提出了一種使用搭載計算機視覺的智能無人機估算藍莓產量的方法。系統利用兩個YOLO模型&#xff1a;一個檢測灌木叢&#xff0c;另一個檢測漿果。它們協同工作&#xff0c;智能控制無人機位置和角度&#xff0c;安全獲取灌木近景圖&#xff0c;實現精準的漿果計數…

API 管理系統實踐指南:監控、安全、性能全覆蓋

在數字化轉型和云原生架構全面普及的當下&#xff0c;API&#xff08;應用編程接口&#xff09; 已成為現代技術和業務架構的核心基石。從移動應用到智能硬件&#xff0c;從企業后端系統到 AI 模型調用&#xff0c;幾乎所有系統都在通過 API 實現互聯互通。API 這個詞聽起來有點…

Leetcode-?930. 和相同的二元子數組?

Problem: 930. 和相同的二元子數組 思路 滑動窗口 解題過程 我們可以通過計算 和大于等于 goal 的子數組數目 與 和大于等于 goal1 的子數組數目 的差值&#xff0c;來得到 和恰好等于 goal 的子數組數目。 Code c class Solution { public:int at_most(vector<int>&…

『大模型筆記』第1篇:高效請求排隊:優化大語言模型(LLM)性能

『大模型筆記』高效請求排隊:優化大語言模型(LLM)性能 文章目錄 一. 起點:基礎的推理引擎二. 問題:“重度用戶”會阻塞其他用戶三. 解決方案:公平調度3.1. 擴展思路四. 問題:后端隊列沒有“反壓”機制五. 解決方案:獲取后端指標5.1 擴展思路六. 替代方案:后端優先級調…

Docker Docker Compose 一鍵安裝

目錄 獲取安裝腳本文件執行安裝腳本文件文章結束?? 注意事項&#xff1a;Docker V1 與 V2 的區別 一行命令裝 docker 和 docker compose。 你是否厭倦了在不同的 Linux 系統上一遍又一遍地手動安裝 Docker 和 Docker Compose&#xff1f;&#x1f914; 不論你是 Ubuntu 、Deb…

Java 單例模式實現方式

Java 單例模式實現方式 單例模式是確保一個類只有一個實例&#xff0c;并提供一個全局訪問點的設計模式。以下是 Java 中實現單例模式的幾種常見方式&#xff1a; 1. 餓漢式&#xff08;Eager Initialization&#xff09; public class EagerSingleton {// 類加載時就初始化p…

數字化零售如何全面優化顧客體驗

一、引言 數字化零售是互聯網、大數據、人工智能等技術在零售業中的應用&#xff0c;是現代零售業發展的必然趨勢。隨著線上購物、移動支付和全渠道銷售的普及&#xff0c;零售行業發生了顛覆性的變化。數字化零售不僅提高了企業運營效率&#xff0c;更為顧客提供了便捷、個性化…

rabbitmq 交換機、隊列和消息概念

RabbitMQ 是一個功能強大的消息中間件&#xff0c;它采用發布-訂閱模式進行消息傳遞。下面為你詳細介紹 RabbitMQ 中交換機、隊列和消息的核心概念。 交換機&#xff08;Exchange&#xff09; 交換機在 RabbitMQ 中扮演著接收生產者發送消息的角色&#xff0c;它會根據特定的…

記錄一次jenkins slave因為本地安裝多個java版本導致的問題

今天&#xff0c;使用jenkins打包&#xff0c;發現slave掉線&#xff0c;上對應機器一看&#xff0c;好家伙&#xff0c;slave運行不起來了。命令行&#xff0c;java -vesion. 沒反應&#xff0c;不會是哪個天殺的把java 給卸載了吧&#xff01; 趕緊 where java看下。 還好 ja…

Java中Redis常用的API及其對應的原始API

相信大家寫redis的時候經常忘記一些指令吧[狗頭][狗頭]&#xff0c;這里整理了一下 一、 String&#xff08;字符串類型&#xff09; 1.代碼塊 // 設置字符串值 stringRedisTemplate.opsForValue().set("key", "value"); // Redis: SET key value// 設置…