为何空类型组成的std::variant实现占用空间超过1字节?
这基本是个冷门问题,我认为我大概率不会有需要用到这种空间节省的场景。
我在测试时发现,libstdc和libc的std::variant实现,存储由空结构体组成的variant时占用空间都超过1字节:
- libstdc++实现占用2字节
- libc实现占用8字节
我猜测是做这类优化的性价比太低不值得,但我想了解是否存在其他原因,尤其是C标准中关于std::variant的表述是否禁止了这类优化。
标准是否禁止这类优化
C++标准没有禁止对仅包含空结构体的std::variant做空间压缩到1字节的优化。标准仅对std::variant的功能行为做约束:比如需要正确识别当前活跃的备选类型、满足对应类型的复制/移动语义、保证异常安全等,没有对存储布局的大小设置强制下限,这类空间优化完全符合标准要求。
主流标准库不做优化的核心原因
- 场景过于冷门,性价比极低:仅存储空结构体的
std::variant是非常极端的使用场景,几乎不会出现在实际生产代码中。为了这种几乎无人使用的场景单独开发特化逻辑,会大幅增加标准库的维护成本,收益却可以忽略不计,完全没有必要。 - 通用实现的固有开销:常规
std::variant的通用实现会单独设置一个discriminator(类型索引)字段,用来标记当前活跃的备选类型,通常默认用1字节的uint8_t存储。而C要求任何完整对象的大小至少为1字节,空结构体本身也会占1字节,两者组合后对齐就得到了libstdc的2字节结果。libc++的实现为了兼容更多通用特性(比如constexpr支持、更复杂的emplace异常安全逻辑),discriminator采用了更大的整数类型,对齐后最终占用8字节。 - 不影响常规场景的效率:对于绝大多数实际使用的
std::variant,备选类型中都会包含非空类型,discriminator的大小会被更大的备选类型的对齐要求覆盖,不会额外占用空间,这类冷门场景的优化对常规使用没有任何收益。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

