Some Windows APIs取slice作为参数,返回时写入.它类似于out指针,但采用切片形式(这样调用者就不需要传递额外的"length"参数).

在out指针的情况下,我一直使用MaybeUninit,我认为这是Rust中惯用的方式.然而,我不知道如何在切片的情况下使用它.

例如,许多示例建议声明[MaybeUninit<u16>; 32],但如何将其传递给只接受&mut [u16]的函数?我try 了MaybeUninit<[u16; 32]>,但无法从MaybeUninit中获得未初始化的&mut T.只有as_mut_ptr个,这是指针,不是切片.

我现在应该坚持let x: [u16; 32] = zeroed();吗?

推荐答案

创建对未初始化内存的引用是未定义的行为,即使从未读取内存内容.引用the reference, "Behavior considered undefined"(强调我的):

  • ...
  • Producing an invalid value, even in private fields and locals. "Producing" a value happens any time a value is assigned to or read from a place, passed to a function/primitive operation or returned from a function/primitive operation. The following values are invalid (at their respective type):
    • ...
    • A referenceBox<T>表示dangling,未对齐,or points to an invalid value.

...

Note: Uninitialized memory is also implicitly invalid for any type that has a restricted set of valid values. 换句话说,允许读取未初始化内存的唯一情况是在联合内部和"填充"(类型的字段/元素之间的间隙)中.

这不是obvious,这是UB:有an active discussion about that(部分反驳是为了允许像你这样的事情).然而,目前它被认为是UB,你应该避免它.

(注意:"具有一组受限的有效值"有点模棱两可.是否允许像整数这样的基元类型包含未初始化的位是also a matter of active discussion,但在这种情况下,您也应该避免它,直到解决为止.您可能会声称引用不同意这一点,因为整数没有限制的值集,但这是错误的:可以将一个字节的可能值集视为0-256 and uninit字节,事实上这是在许多地方使用的解释.整数不能包含uninit字节,因此具有一组受限的值).

使用mem::zeroed()初始化数组是合理的,但没有理由使用unsafe:您可以只使用一个已初始化的数组,即[0; size],它的性能也一样.

Rust相关问答推荐

为什么拥有的trait对象的相等运算符移动了正确的操作数?

程序退出后只写入指定管道的数据

从Rust调用C++虚拟方法即使在成功执行之后也会引发Access违规错误

如何容器化Linux上基于Rust的Windows应用程序的编译过程?

如何创建引用构造函数拥有的变量的对象?

何时可以在Rust中退出异步操作?

在特征中使用Async时,如何解决不透明类型`impl Future<;out=self>;`不满足其关联的类型边界和警告?

MPSC频道在接收器处阻塞

无法将记录器向下转换回原始 struct

除了调用`waker.wake()`之外,我如何才能确保future 将再次被轮询?

更合理的方法来设计样条线函数器?

写入引用会更新基础值,但引用会打印意外的值

如何轮询 Pin>?

在 Rust 中用问号传播错误时对类型转换的困惑?

Rust中如何实现一个与Sized相反的负特性(Unsized)

Rust编译器通过哪些规则来确保锁被释放?

如何解析 Rust 中的 yaml 条件字段?

如何将切片推入数组?

Rust 生命周期:不能在方法内重新borrow 可变字段

在传输不可复制的值时实现就地枚举修改