深入理解 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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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// 设置…