constexpr、 consteval、 constinit

下面分三部分:constexpr 的作用、常见面试题、常见坑。代码没有实测,编译器限制的数值来自 GCC 文档,属于实现细节。 一、constexpr 究竟有什么用 它让一段计算可以在编译期完成,并且让计算结果能用在"必须是常量"的地方。 具体有四类用处: 用处例子1. 在要求常量表达式的地方使用计算结果数组大小、模板实参、case 标签、static_assert、alignas、枚举值2. 把运行时的开销挪到编译期查找表、CRC…

xiedeacc 发布于 阅读 54

lambda表达式

下面分成"常见面试题"和"常见坑"两部分。代码没有实测过,涉及 sizeof 的数值以 GCC/libstdc++(x86_64)为准,属于实现细节。 一、常见面试题 1. lambda 的本质是什么 lambda 表达式会生成一个匿名类(闭包类型)的对象: 捕获的变量成为这个类的数据成员。 函数体成为这个类的 operator(),而且默认是 const 成员函数。 每个 lambda 表达式都有自己独一无二的类型。即使两个…

xiedeacc 发布于 阅读 54

SFINAE

xiedeacc 发布于 阅读 14

auto和decltype

有,而且用得很多。C++14 引入了返回类型推导(auto f() { ... }),以前 auto f() -> decltype(expr) 这种尾置返回类型大多可以不写了,所以容易让人觉得 decltype 没用了。实际上,auto 只能"推导一个值的类型",decltype 能"精确查询一个表达式的类型",两者不能互相替代。 根本区别:auto 会退化,decltype 不会 它的规则只有两条:…

xiedeacc 发布于 阅读 11

无锁

结论 不完全是。std::atomic 是语言层面的抽象,底层怎么实现取决于类型大小、CPU 架构和具体操作。以现代 x86-64 为例: 普通的 load 和 store 什么都不锁,就是一条普通的 mov。 读-改-写操作(fetch_add、exchange、compare_exchange)用的是带 lock 前缀的指令。在现代 CPU 上,lock 锁的是缓存行,不是总线。…

xiedeacc 发布于 阅读 21

condition_variable

2. condition_variable 如何实现事件驱动 核心是:等待线程在内核里睡眠,不占用 CPU;通知线程把它唤醒。 等待期间,这个线程从调度器的运行队列里摘掉,完全不会被调度。条件满足后由通知方把它放回运行队列。这就是"事件驱动",与之相对的"轮询"是线程自己反复醒来检查条件。 方式等待期间 CPU响应延迟忙等 while (!ready);占满一个核最低睡眠轮询 while (!ready)…

xiedeacc 发布于 阅读 19

CRTP和PIMPL

1. 什么是 CRTP CRTP 的全称是 Curiously Recurring Template Pattern,中文叫"奇异递归模板模式":派生类把自己作为模板参数传给基类。 基类在编译期就知道派生类的确切类型,可以直接 static_cast 过去调用派生类的函数。这样得到的是静态多态:没有虚函数表,没有间接调用,调用可以被内联。 虚函数(动态多态)CRTP(静态多态)分派时机运行时,查…

xiedeacc 发布于 阅读 12

Cache miss和TLB miss

cache 缓存数据,TLB 缓存地址翻译结果。 一次访存要先过 TLB 拿到物理地址,再拿物理地址去查 cache,所以它们是串在一条路上的两道关卡。 Cache miss CPU 拿着物理地址去 L1/L2/L3 找那一行数据(64 字节),没找到就往下一级找,最后到内存。 是数据不在片上。 硬件全程处理,软件无感知。 代价是一次内存访问的延迟。 TLB miss CPU 拿着虚拟地址去 TLB…

xiedeacc 发布于 阅读 13

C++/Rust/Golang协程

有栈协程 vs 无栈协程 一、核心原理 有栈协程(Stackful Coroutine) 每个协程拥有独立的运行栈(通常在堆上分配,几 KB 到几 MB),切换时保存/恢复 CPU 寄存器上下文(rsp、rip、callee-saved 寄存器等),本质上是用户态线程。 切换过程(以 x86-64 为例): 把当前寄存器压入当前协程的栈 把 rsp 指向目标协程的栈顶 弹出目标协程之前保存的寄存器 ret 跳转到目标协程上次挂起的位置…

xiedeacc 发布于 阅读 154