auto和decltype
有,而且用得很多。C++14 引入了返回类型推导(auto f() { ... }),以前 auto f() -> decltype(expr) 这种尾置返回类型大多可以不写了,所以容易让人觉得 decltype 没用了。实际上,auto 只能"推导一个值的类型",decltype 能"精确查询一个表达式的类型",两者不能互相替代。 根本区别:auto 会退化,decltype 不会 它的规则只有两条:…
有,而且用得很多。C++14 引入了返回类型推导(auto f() { ... }),以前 auto f() -> decltype(expr) 这种尾置返回类型大多可以不写了,所以容易让人觉得 decltype 没用了。实际上,auto 只能"推导一个值的类型",decltype 能"精确查询一个表达式的类型",两者不能互相替代。 根本区别:auto 会退化,decltype 不会 它的规则只有两条:…
结论 不完全是。std::atomic 是语言层面的抽象,底层怎么实现取决于类型大小、CPU 架构和具体操作。以现代 x86-64 为例: 普通的 load 和 store 什么都不锁,就是一条普通的 mov。 读-改-写操作(fetch_add、exchange、compare_exchange)用的是带 lock 前缀的指令。在现代 CPU 上,lock 锁的是缓存行,不是总线。…
2. condition_variable 如何实现事件驱动 核心是:等待线程在内核里睡眠,不占用 CPU;通知线程把它唤醒。 等待期间,这个线程从调度器的运行队列里摘掉,完全不会被调度。条件满足后由通知方把它放回运行队列。这就是"事件驱动",与之相对的"轮询"是线程自己反复醒来检查条件。 方式等待期间 CPU响应延迟忙等 while (!ready);占满一个核最低睡眠轮询 while (!ready)…
1. 什么是 CRTP CRTP 的全称是 Curiously Recurring Template Pattern,中文叫"奇异递归模板模式":派生类把自己作为模板参数传给基类。 基类在编译期就知道派生类的确切类型,可以直接 static_cast 过去调用派生类的函数。这样得到的是静态多态:没有虚函数表,没有间接调用,调用可以被内联。 虚函数(动态多态)CRTP(静态多态)分派时机运行时,查…
cache 缓存数据,TLB 缓存地址翻译结果。 一次访存要先过 TLB 拿到物理地址,再拿物理地址去查 cache,所以它们是串在一条路上的两道关卡。 Cache miss CPU 拿着物理地址去 L1/L2/L3 找那一行数据(64 字节),没找到就往下一级找,最后到内存。 是数据不在片上。 硬件全程处理,软件无感知。 代价是一次内存访问的延迟。 TLB miss CPU 拿着虚拟地址去 TLB…
有栈协程 vs 无栈协程 一、核心原理 有栈协程(Stackful Coroutine) 每个协程拥有独立的运行栈(通常在堆上分配,几 KB 到几 MB),切换时保存/恢复 CPU 寄存器上下文(rsp、rip、callee-saved 寄存器等),本质上是用户态线程。 切换过程(以 x86-64 为例): 把当前寄存器压入当前协程的栈 把 rsp 指向目标协程的栈顶 弹出目标协程之前保存的寄存器 ret 跳转到目标协程上次挂起的位置…
这是个经典题。方法有很多,但只有两种是标准 C++,其余都是平台扩展。 一、在 main 之前运行 方法 1:全局/静态对象的构造函数 —— 标准做法 before main main after main 唯一可移植的方案。 原理见 memory-layout.md:这些构造函数的指针被放进 .init_array,由 C 运行时在 __libc_start_main 里遍历调用。 方法 2:用全局变量的初始化式调用函数…
这是个接口设计问题,核心判据只有一条:引用的三个"不能"。 一、根本判据 引用有三个硬限制: 限制后果不能为空需要表达"可能没有"时用不了不能重新绑定需要改指向、需要迭代时用不了不是对象(没有自己的地址)不能放容器、不能做数组元素需要这三者之一 → 用指针。否则 → 用引用。 其余的讨论都是这条规则的展开。 二、决策表 需求签名说明只读,大对象const T&默认选择只读,小且平凡(≤16…