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

【c++八股文】Day5:const和constexpr,define

非常棒的问题,这几个关键字(constconstexpr#define)都可以用来表示“常量”,但它们意义、作用时机和参与编译的方式完全不同,理解这些对掌握 C++ 编译模型和写出高质量代码非常重要。

我们从用途、语义、生命周期、编译阶段、类型检查、作用域、性能优化等维度系统性整理:


✅ 一、先看三者的简要对比

特性/关键词#defineconstconstexpr
类型安全❌(纯文本替换)✅(有类型)✅(有类型,且编译期常量)
编译阶段预处理阶段编译阶段编译阶段(要求常量表达式
编译器可见性❌(对编译器不可见)✅(符号存在)✅(符号存在且常量可折叠)
优化能力差(不利于调试优化)较好最佳
可以取地址✅(在符号表中)✅(但可能折叠为立即数)
支持复杂类型❌(只能是文本)
可用于数组长度✅(C++11起)
常量表达式限制不要求是编译期常量必须是编译期常量表达式

🧩 二、编译器行为层面解释

1. #define:预处理阶段文本替换

#define PI 3.14

🔍 行为:

  • 预处理阶段,编译器会把 所有出现 PI 的地方直接替换为 3.14
  • 编译器看不到 PI 这个标识符,调试器、类型系统也看不到
  • 不参与类型检查、作用域控制

📌 不推荐:

#define SQUARE(x) x * x
int y = SQUARE(1 + 2);  // → 展开为 1 + 2 * 1 + 2 → 错误

2. const:在编译阶段处理的只读变量

const double pi = 3.14;

🔍 行为:

  • pi 是一个具有类型和作用域的符号
  • 编译器会参与类型检查
  • 可以取地址(存在符号表中)
  • 如果优化器看到它不变,可能优化为立即数

📌 示例:

const int N = 10;
int arr[N];  // C++11 起允许

3. constexpr:编译阶段就能求值为常量的表达式

constexpr double pi = 3.14;
constexpr int square(int x) { return x * x; }

🔍 行为:

  • 要求变量或函数在编译期间就能确定值

  • 编译器会强制执行常量折叠(constant folding)

  • 可用于:

    • 数组大小
    • 模板参数
    • 枚举值
    • if constexpr 语句分支
  • 可定义常量表达式函数

📌 示例:

constexpr int N = square(3); // N = 9,在编译期完成计算
int arr[N];                  // 数组大小合法

⚠️ 三者在调试器中的差异

内容类型在调试器中是否可见是否能打断点是否能取地址
#define❌ 不可见(被替换掉)❌ 无法断点
const✅ 可见(有符号名)✅ 可以断点
constexpr⚠️ 可能折叠优化掉❌ 不一定能断点❌ 常常变成立即数

✅ 四、代码层级对比示例

#define LEN 100                     // 无类型,只是 100 的文本替换const int len1 = 100;              // 有类型,支持类型检查,可能折叠
constexpr int len2 = 100;          // 编译期常量,支持最强优化int arr1[LEN];   // ✅
int arr2[len1];  // ✅(C++11 起)
int arr3[len2];  // ✅(优先推荐)

🎓 五、适合用于什么场景?

使用场景推荐选项原因
简单常量替代constexpr类型安全 + 编译期求值 + 优化好
宏函数inline constexpr function避免宏展开错误,可调试
魔法数字、配置参数constexpr or const类型安全、可调试
条件编译(平台相关)#ifdef/#define预处理器语法只在这类场景合法
定义模板参数或数组大小constexpr编译期要求常量

✅ 六、语义分层总结图

       ┌────────────────────────────┐│       #define PI 3.14      │ ← 预处理,替换文本,无类型、无调试信息└────────────────────────────┘↓┌────────────────────────────┐│  const double pi = 3.14;   │ ← 有类型,有符号,有作用域,可调试└────────────────────────────┘↓┌────────────────────────────┐│ constexpr double pi = 3.14;│ ← 编译期常量表达式,最优性能和安全性└────────────────────────────┘

✅ 七、一句话总结

#define 是预处理器的文本替换,完全不参与类型系统;const 是只读变量,具有类型和作用域;constexpr 是编译期可求值的常量表达式,是现代 C++ 推荐的写法,支持最强类型安全与编译优化。

http://www.lryc.cn/news/583277.html

相关文章:

  • 【话题长廊测试报告】
  • 【算法深练】DFS题型拆解:沿着路径“深挖到底”、递归深入、回溯回探的算法解题思路
  • Day21
  • 自然灾害应急响应场景数据资产化研究报告
  • 一台云服务器可以备案几个网站
  • 【数据分析】多数据集网络分析:探索健康与退休研究中的变量关系
  • PiscTrace应用:从 YOLO-Pose 到深蹲与引体向上计数:实时健身动作分析与实现
  • AI芯片产品经理:算力革命的架构师
  • 【macOS】【Swift】【RTF】黑色文字在macOS深色外观下看不清的解决方法
  • 【洁净室自净时间测试】检测粒径选择的深入分析与优化建议
  • python实践思路(草拟计划+方法)
  • HashMap的get、put流程源码分析
  • sql查询davinci看板数据
  • 《解构this:JavaScript中动态指向的隐秘逻辑》
  • PHP语法高级篇(一):日期时间处理和包含文件
  • 美股异动|机器人概念表现活跃,微美全息(WIMI.US)瞄准高增长赛道涨超14%
  • 2023年IEEE TITS SCI2区TOP,增强回溯搜索算法EBSA+多无人机辅助商业包裹递送系统飞行规划,深度解析+性能实测
  • 第4章:实战项目一 打造你的第一个AI知识库问答机器人 (RAG)
  • LeetCode 138题解 | 随机链表的复制
  • 光伏无人机3D建模:毫秒级精度设计
  • 老年人与机器人玩具的情感连接
  • 什么是 AMR 格式?简鹿音频转换器轻松批量转换 AMR 为 MP3
  • 论文阅读|汽车虚拟环绕音响系统设计与实现策略的比较研究
  • OpenCV图片操作100例:从入门到精通指南(4)
  • NLP:初识RNN模型(概念、分类、作用)
  • 继承与多态:面向对象编程的两大支柱
  • stockapi股票实时tick数据,技术指标macd,kdj,cci,日k线数据
  • 如何将FPGA设计的验证效率提升1000倍以上(3)
  • oracle ocp题库有多少道题,以及题库背诵技巧
  • JavaEE初阶第八期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(六)