各位老师好!

这是CPP面试冲刺周刊 (c++ weekly) 陪你一起快速冲击大厂面试 第7期

周刊目标

  • 不是成为C++专家,而是成为C++面试专家

本期内容

  • constexpr、内联函数、编译期元编程

常见误区(反常识):

  • const 修饰变量 分配内存空间吗?什么时候分配,什么时候不分配

一、背景与初衷:为什么 C++11 引入 constexpr

1. 过去的问题:#defineconstinline 的局限

  • #define 宏常量:不参与类型检查,调试困难。

  • const 变量:虽然安全,但在 C++11 之前,const 不保证编译期常量

  • inline 函数:通过内联展开减少函数调用开销,但依然在 运行期计算

我们会遇到这种场景:

1
2
const int NODE_NUM = 3; //在 C++98 中只是一个 运行期常量,不是 编译期常量。
char buf[NODE_NUM]; // 编译直接报错

因为 NODE_NUM 不是编译期常量,buf 的大小无法在编译期确定,编译错误。

C++11 引入 constexpr,让我们可以在 编译期完成计算,避免运行时开销。

C++11 引入 constexpr 的初衷

C++11 引入了 constexpr,目标是:

  • 常量表达式编译期完成求值;

  • 提高 性能,减少运行期不必要的计算;

  • 统一常量语义,避免编译器行为不一致。

改写上面的例子:

constexpr int NODE_NUM = 3; char buf[NODE_NUM]; // ✅ 编译期直接展开

编译器会在 编译期直接把 NODE_NUM 计算成 3,

生成的汇编里,buf 是一个 固定大小的栈数组,根本不会在运行期再算一次。


二、技术优势与劣势

特性 inline const / constexpr 编译期元编程(模板 + constexpr
目标 减少函数调用开销 固定值、优化常量表达式 利用编译期完成复杂逻辑
性能 消除调用栈,但仍然运行期求值 const 多为运行期,constexpr 编译期计算 完全避免运行期开销
适用场景 高频调用的短函数 常量定义、查表、状态切换 哈希计算、调度策略、数据映射表
缺点 代码膨胀、编译时间增加 constexpr 在 C++11 较受限,C++14 才支持更复杂逻辑 编译时间长、代码可读性差

3fs:代码

static constexpr size_t kNodeIdKeyedMapExpectedNumElements = 1000;

constexpr int kNumIovecs = 64;

std::array<iovec, kNumIovecs> iovecs;

constexpr uint32_t kInvalidatedFlag = 1u « 0u; // Bit 0

constexpr uint32_t kReadAvailableFlag = 1u « 1u; // Bit 1

constexpr uint32_t kReadNewWakedFlag = 1u « 2u; // Bit 2

constexpr uint32_t kWriteAvailableFlag = 1u « 3u; // Bit 3

constexpr uint32_t kWriteNewWakedFlag = 1u « 4u; // Bit 4

constexpr uint32_t kWriteHasMsgFlag = 1u « 5u; // Bit 5

constexpr uint32_t kWriteNewMsgFlag = 1u « 6u; // Bit 6

constexpr uint32_t kLastReadFinished = 1u « 7u; // Bit 7

constexpr uint32_t kLastWriteFinished = 1u « 8u; // Bit 8


三、适用场景

在分布式存储和数据库的高性能项目中,constexpr 和编译期元编程适用于 大量重复计算 的场景:

  1. 哈希值计算
    Ceph 的 PG 映射里会用到哈希:

    1
    2
    3
    4
    
    constexpr uint32_t hash(const char* s, size_t n) {
        return n ? (hash(s, n-1) * 131 + s[n-1]) : 0;
    }
    constexpr auto key = hash("pool1", 5);
    
    • 收益:hash 在编译期算完,运行期不消耗 CPU。
  2. 常量查表
    比如 TiDB 的执行计划优化:

    1
    
    constexpr std::array<int, 4> priorities = {1, 2, 4, 8};
    
    • 收益:常量表编译期固化,避免 runtime 初始化。
  3. 模板 + constexpr 的高性能策略调度

    1
    2
    3
    4
    5
    
    template <typename Strategy>
    constexpr auto choose_strategy() {
        if constexpr (std::is_same_v<Strategy, SSD>) return "low-latency";
        else return "high-throughput";
    }
    
    • 收益:调度策略完全在 编译期分发,零运行时分支判断。

四、底层原理

constexpr 的本质是 把一部分运行期逻辑前移到编译期,核心是:

  1. 语法约束
    C++11 要求 constexpr 函数必须:

    • 单个 return 表达式

    • 不允许循环和复杂控制流

    • 不允许动态分配内存
      → C++14 以后放宽限制,可以写递归、if-else 等复杂逻辑。

  2. 编译器行为

    • 如果输入是编译期常量 → 在编译期计算结果,直接写死到目标代码。

    • 如果输入是运行时值 → 退化为普通函数,在运行期执行。

  3. 示例:编译器直接展开常量

    1
    2
    
    constexpr int square(int x) { return x * x; }
    int a = square(3);
    

    编译器会直接把 a 展开为:

    1
    2
    
    mov eax, 9
    mov [a], eax
    

    没有函数调用,也没有乘法指令


五、与模板元编程结合:C++17/20 的 constexpr 进化

在 C++17 和 C++20,constexpr模板元编程 深度结合,让我们能写出接近函数式语言的代码:

1
2
3
4
5
6
template <typename T>
constexpr size_t type_id() {
    if constexpr (std::is_same_v<T, int>) return 1;
    else if constexpr (std::is_same_v<T, double>) return 2;
    else return 0;
}
  • C++17if constexpr 让模板分支只保留必要的代码,消除了未使用分支的编译错误。

  • C++20consteval 更进一步,强制 编译期求值,让性能更加可控。


六、总结与实践建议

技术 用途 收益 注意事项
inline 展开函数,消除调用开销 小幅提升性能 代码膨胀
constexpr 编译期计算 避免运行期重复计算,零开销 C++11 受限,C++14+ 更强大
模板 + constexpr 编译期分发策略 极致性能优化 编译时间、可读性

实践建议

  • 高频小函数:优先 constexpr

  • 大型查表、哈希:constexpr + std::array

  • 策略分发:if constexpr + 模板

  • 性能敏感核心逻辑:结合 consteval 强制编译期求值


面试准备心得

曾经有一个让我心跳加速的岗位放在我面前,
我没有珍惜。
等到别人拿到 offer 的那一刻,
我才追悔莫及!

人世间,最痛苦的事情,
不是没钱吃饭,
也不是没房没车,
而是——错过了那个能让我逆天改命的机会!

如果上天再给我一次机会,
我一定会对那个岗位说三个字:
“我要你!”

如果非要在这份“心动”上加一个期限,
一万年太久了……
我只想要——21天!

你可能面临两种选择

① 犹豫不前:准备到天荒地老

“这个岗位太难了,我先准备一下吧。”
于是你准备1天、1周、1个月、1年……
等再回头,3年就这样过去了

  • 每天忙着搬砖,没时间系统复习
  • 每次想起要准备,又感觉心里没底
  • 面试知识点更新太快,拿着旧地图找新机会 最后,错过了一次又一次心动的岗位。

② 盲目回答:机会就在眼前,却抓不住

终于等来一场面试,
你觉得问题很简单,张口就答,
结果用“几千元思维”回答“百万年薪岗位”。

  • 面试官问到C++底层实现,答不上来
  • 设计题说到高并发架构,没实战经验
  • 一紧张,连项目里真实做过的东西都讲不清

一次面试失利,也许就意味着和理想岗位失之交臂。

更残酷的是

在你犹豫的这几年里,
找工作的成本越来越高:

  • 一个部门、一个领导,可能坚持一年就被解散
  • 一个项目,可能在10年、20年后,
    曾经复杂的业务规则、先进的架构,早已被淘汰
  • 市场上新的技术和面试要求,每年都在不断升级

等你回过头来,发现不仅机会没了,
连准备的方向都变了

不是让你成为C++专家, 而是让你成为C++面试专家

不是让你疯狂学习新知识, 而是帮你重新整理已有知识
让你的能力与面试题精准对齐。

因为,21天就够了,
足够让我火力全开,

  • 一边补齐 C++ 知识点,
  • 一边刷爆经典面试题,
  • 一边撸穿开源项目,
  • 让自己变得不可替代!

核心方法论

让你学到每个 c++知识,都关联一个经典面试,并对对应开源项目实践

  • 系统备战
    每天 20~30 分钟,聚焦 C++ 核心知识,
    三周时间完成高效梳理。

  • 经典面试题
    每个知识点都关联一个高频面试题
    让你知道“为什么考”和“怎么答”。

  • 开源项目实践
    通过真实项目理解底层原理,
    不背答案,而是用实践打动面试官

  • 场景驱动学习
    还原真实面试场景,
    帮你学会“怎么说服面试官”。

  • 三周后,面对面试官,你能自信说出:
    *“问吧,准备好了。”

最动人的作品,为自己而写,刚刚好打动别人

 1️⃣ 如果有更多疑问,联系小王,一起交流,进步

个人联系方式

2️⃣  关注公众号:后端开发成长指南(回复"面经"获取)获取过去我全部面试录音和面试复盘。

抬头看天:走暗路、耕瘦田、进窄门、见微光

  • 不要给自己这样假设:别人完成就等着自己完成了,大家都在一个集团,一个公司,分工不同,不,这个懒惰表现,这个逃避问题表现。
  • 别人不这么假设,至少本月绩效上不会写成自己的,至少晋升不是你,裁员淘汰就是你。
  • 目标:在跨越最后一道坎,拿百万年薪,进大厂。