第25章:细则
为什么有这一章
教程必须选择顺序。有些特性太小,不值得单独一章;有些太依赖场景,不适合主路径;有些只是掉在两个主题之间。 它们仍然出现在真实代码里,而且出现时,编译器的行为往往令人意外。
这一章收集前面没有覆盖的那些:共用体、结构化绑定、存储期与链接、匿名与内联命名空间、条件
explicit、[[no_unique_address]]、对齐、offsetof 和
volatile。每一页是一组规则,不是标准库导览。
有一个特性刻意不在这里重复:using enum 属于它影响的枚举,已经在
第2.16章讲过。放在那里可以避免把同一条作用域规则教两遍。
四页
简短版本
union 让所有非静态数据成员共享一块存储。只能读活动成员;公共初始序列是窄例外。
非平凡成员需要显式构造和析构。位域依赖布局,不是可移植线格式。共用体类型双关在 C++ 里是未定义行为;
用 std::bit_cast 或 memcpy。
结构化绑定把多个名字绑定到一个隐藏对象的元素上。数组、类 tuple 类型和公开聚合体成员可以被分解。
声明的限定符作用于隐藏对象:auto 复制,auto& 别名,
auto const& 延长临时对象,auto&& 转发。名字数量必须等于元素数量。
作用域、存储期和链接互相独立。局部 static 每个程序一个对象,只初始化一次。
thread_local 每线程一个对象,不是同步。inline 变量在头文件里跨翻译单元
提供一个实体。命名空间作用域的 const 默认内部链接。匿名命名空间是每翻译单元的实现细节;
内联命名空间是透明版本化。
explicit(bool) 让显式性成为编译期条件。[[no_unique_address]] 允许空成员
重叠,但不保证大小。alignas 提高对齐;alignof 询问对齐。
offsetof 用于标准布局类型,且依赖 ABI。volatile 用于硬件和信号,
不用于线程间同步。
要点
- union 用一份存储装多种类型;跟踪活跃成员是你的责任。
- 结构化绑定分解聚合和 tuple-like 类型。
- 存储期、链接性和命名空间决定生命周期与可见性。
- 这些尖角是真实存在的;有更安全的构造时就优先用它。