当前位置: 首页 > 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.lryc.cn/news/607689.html

相关文章:

  • 查看主板信息的3种方法
  • PL-0功能拓展及基于VSCode的IDE配置
  • QT开发---图形与图像(补充)
  • 逻辑斯蒂回归的模型优化
  • 疯狂星期四文案网第26天运营日记
  • 台式机 Server 20.04 CUDA11.8
  • 上海月赛kk
  • 电力系统与变压器实验知识全总结 | 有功无功、同步发电机、短路空载实验、电压调整率、效率条件全讲透!
  • 学习嵌入式第十七天
  • 基于coze studio开源框架二次定制开发教程
  • 幂等性校验(订单重复提交问题)
  • IOMMU Client设备DMA配置过程分析(九)
  • STM32 使用 RTC 实现实时时钟功能
  • C语言:20250801学习(构造类型)
  • 机器学习:开启智能时代的钥匙
  • MySQL 高并发下如何保证事务提交的绝对顺序?
  • 学习笔记:原子操作与锁以及share_ptr的c++实现
  • synchronized 深度剖析:从语法到锁升级的完整演进
  • 什么是Sedex审核?Sedex审核的主要内容,Sedex审核的流程
  • 通用障碍物调研
  • 【C++进阶】一文吃透静态绑定、动态绑定与多态底层机制(含虚函数、vptr、thunk、RTTI)
  • 测试分类:详解各类测试方式与方法
  • 使用gcc代替v语言的tcc编译器提高编译后二进制文件执行速度
  • Trust Management System (TMS)
  • MySQL锁的分类 MVCC和S/X锁的互补关系
  • Linux编程: 10、线程池与初识网络编程
  • GESP2025年6月认证C++八级( 第三部分编程题(1)树上旅行)
  • 链表【各种题型+对应LeetCode习题练习】
  • 《C++》STL--list容器详解
  • UnionApplication