当前位置: 首页 > news >正文

c++详解(宏与内联函数,nullptr)

目录

1.宏

2.c++中宏的代替者

3.宏自身的优缺点。

3.1宏的缺点

3.2宏的优点

4.inline

5.使用inline的注意点

6.nullptr

摘要


1.宏

关于宏的定义,不了解的朋友可以点击链接跳转至编译与链接博客,其中预编译部分有详细介绍。

2.c++中宏的代替者

我们知道,c语言中宏可以定义常量,定义函数,虽然在cpp中宏仍可用,但在cpp中我们建议使用

const 、enum(枚举,不了解的朋友可以点击链接跳转至联合体与枚举博客)来代替宏创建常量,用inline(内联)来代替宏函数。

原因在于

3.宏自身的优缺点。

3.1宏的缺点

宏的操作本质上是一个“代替”的操作,在预编译阶段,会对宏进行简单的文本替换,这个特性使得使用宏时要考虑宏的各种副作用(常量的前后置++--等)和各种操作符的优先级(写宏函数要加各种括号),导致宏函数很复杂还容易出错,因为是文本替换的原因,宏在预处理被展开,宏函数不会建立函数栈帧,这也使得宏函数没法调试

3.2宏的优点

由于宏函数的使用(区别与调用)不需要创建函数栈帧,且高频调用函数的函数结构比较简单,常被写成宏函数,可以节省空间,提高效率

4.inline

用于修饰函数,被inline修饰的函数就叫内联函数,与宏的展开相似,内联函数在编译(在预处理的下一时期,编译的第二阶段,不了解的朋友可以点击链接跳转至编译与链接博客了解编译过程)时,编译器会在调用函数的地方展开成相应的逻辑汇编代码,不需要创建函数栈帧,提高效率。因而可以代替宏。

5.使用inline的注意点

  • inline对于编译器来说是一个建议性指令,inline修饰的函数是否被展开,取决于编译器,一般来说代码行数较多的函数,或者递归函数,即使加inline也不会被展开(就是普通的函数)。
  • vs编译器debug版本下,inline默认是不展开的,这样方便调试(展开的话不会创建函数栈帧,无法调试)
  • inline不建议把声明和定义分开在两个文件里,在编译与链接博客中我们知道,在链接时需要把编译阶段产生的符号表进行汇总,并进行符号决议,然后才分配地址内存,如果将声明和定义分开,在没有函数定义的源文件中包含了有函数声明的头文件,在编译时,inline修饰的函数理应展开,但是inline规定,在编译时必须在每个调用点直接会展开,必须在源文件中看到完整的函数定义,只有声明时展不开的,此时会发生编译错误(尝试内联但找不到定义),即使不发生编译错误(取决于编译器),函数成功展开,最后生成的.o文件的符号表中也没有函数的地址(逻辑上内联函数既然已经展开了,也就不需要再去找函数的地址了)(如果定义也在头文件中的话,就能找到函数的地址了,因为定义的第一行的地址就是函数的地址),在链接阶段要汇总编译产生的符号表,进行符号决议和重定位,在符号表中找不到函数地址,会发生链接错误。                                                                                                                              总而言之,把inline修饰的函数直接定义在头文件里一点问题都没有!
  • 需要大量调用的函数,不要用内联或者宏,会造成代码的恶性膨胀 ,比如一个用inline修饰的小函数展开后有20行代码,只调用几次,不用建立函数栈帧,确实提高效率,但是要是调用1万次呢,代码量就会剧增,导致项目文件变得非常大,原来1个g的安装包,变成50个g,得不偿失。

6.nullptr

NULL实际是⼀个宏,在传统的C头⽂件(stddef.h)中,可以看到如下代码:

#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif
c++中NULL可能被定义为字⾯常量0,或者C中被定义为⽆类型指针(void*)的常量,不论哪边,都有缺陷。
void f(int x)
{cout << "f(int x)" << endl;
}void f(int* ptr)
{cout << "f(int* ptr)" << endl;
}int main()
{f(0);//调用上边一个f(NULL);//在c++中,想要调用下边函数,但会错调成上边的函数//f((void*)0);//c语言中f(NULL);相当于f((void*)0);想调用下边的函数,类型不同,还需要强转f(nullptr);//成功调用下边的函数}
C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换
任意其他类型指针类型,但不能隐式转换成整型,上边的矛盾就可解决。

摘要

本文介绍了C++中宏的替代方案及其优缺点,重点讨论了内联函数(inline)和nullptr的应用。宏在C++中虽仍可使用,但存在副作用和调试困难等问题,建议用const/enum替代宏常量,用inline替代宏函数。内联函数在编译时展开,避免函数调用开销,但不适用于复杂或递归函数,且声明与定义需在同一文件以避免链接错误。此外,宏的优点在于节省空间和提升效率,但过度使用会导致代码膨胀。最后,文章指出C++11引入的nullptr解决了NULL在类型推导中的二义性问题,能明确表示空指针,提升代码安全性。

http://www.dtcms.com/a/310603.html

相关文章:

  • 每日面试题18:基本数据类型和引用数据类型的区别
  • 唐克的新游戏
  • 100道题通过CISSP,还剩70分钟
  • 体育数据API接入方式与数据类型详解
  • 连载【流程规划进阶 16/16】完结——35页16.流程的现状分析 【附全文阅读】
  • 达梦数据库权限体系详解:系统权限与对象权限
  • 大模型微调与部署课程笔记
  • FreeRTOS硬件中断发生时的现场
  • Spring AI 与 LangChain4j 对比及入门案例解析
  • Selenium:强大的 Web 自动化测试工具
  • VS Code中配置使用slint(Rust)的一个小例子
  • 亚马逊广告:如何借助AI玩转长尾词提升ROI
  • 伞状Meta分析重构癌症幸存者照护指南:从矛盾证据到精准决策
  • (28)运动目标检测之随机曲线上的离散点进行插值
  • 金智维董事长廖万里出席2025中国科创投资夏季峰会,共话智能体垂直落地新路径
  • deepseek: 批量处理脚本
  • shell脚本的语法使用及例题
  • Vue.js的核心概念
  • LVDS系列23:Xilinx Ultrascale系ISERDESE3原语(一)
  • 系统开机时自动执行指令
  • Java:JWT 从原理到高频面试题解析
  • 04 基于sklearn的机械学习-梯度下降(上)
  • 什么样的业务需要国内动态IP轮换?
  • 第二篇:Linux 文件系统操作:从基础到进阶
  • RAL-2025 | “藏宝图”驱动的具身导航!HAM-Nav:基于手绘地图引导的机器人导航
  • GitPython08-源码解读
  • 进阶08:C#与SQL Server通信
  • 高效连接,3针M12航空插头助您畅行无阻
  • PSA 制氧装置和VPSA 制氧装置技术特点有什么不同
  • [VL|RIS] ReferSAM