You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中创建泛型零大小类型(ZST)的实例?

如何安全创建零大小类型(ZST)的实例?

问题背景

我需要在泛型代码中,当类型参数T是零大小类型(ZST)时创建其实例,同时要严格避免未定义行为(UB):

  • 排除《Rustonomicon》中ptr::read(NonNull::<T>::dangling().as_ptr())的方案,该代码存在UB风险
  • 也不使用std::mem::MaybeUninit::<T>::uninit().assume_init(),同样存在UB风险

核心需求是适配所有ZST类型:

  • 无论该类型是否实现Default trait
  • 覆盖空结构体(struct Zst;、struct Zst{})、空元组(())、空或单值枚举(enum Zst;、enum Zst { TheOnlyValue })、空数组([u8; 0])及各类组合类型

最终要在如下泛型迭代器实现中完成逻辑:

impl<T> Iterator for RawIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if size_of::<T>() == 0 {
            // 这里需要返回T的实例
            Some(???);
        }
        // 非ZST的逻辑...
    }
}

解决方案:使用std::mem::zeroed

优先选择std::mem::zeroed::<T>(),它写法简洁且对所有ZST安全。

为什么zeroed对ZST安全?

零大小类型不占用任何内存空间,zeroed不需要写入实际数据。Rust编译器会将ZST的zeroed调用优化为直接返回合法实例——因为ZST的所有可能实例语义等价(无状态差异),零初始化的结果完全符合类型的合法值要求,不存在UB风险。

最终实现代码

将迭代器中的占位符替换为zeroed即可:

use std::mem::{size_of, zeroed};

impl<T> Iterator for RawIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if size_of::<T>() == 0 {
            // 安全创建ZST实例
            Some(unsafe { zeroed() })
        } else {
            // 非ZST类型的处理逻辑,示例返回None
            None
        }
    }
}

适配验证

这个实现可以处理所有目标ZST类型:

  • 空元组():zeroed()返回合法的()实例
  • 空结构体struct Zst;:直接返回该结构体的唯一实例
  • 单值枚举enum Zst { Only }:返回枚举的唯一有效变体
  • 空数组[u8; 0]:返回合法的空数组实例

注意事项

zeroed需要包裹在unsafe块中,但对于ZST场景,这个unsafe是安全的——既不存在内存初始化问题,也不会违反任何类型的不变量。

内容的提问来源于stack exchange,提问作者Robin Kuzmin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:55:26