根据BYTEMUCK的DOC here,Pod只是一个标记性状.其定义如下:

pub unsafe trait Pod: Zeroable + Copy + 'static { }

我对"标记特征"的理解是:它的目的是声明某些类型具有一些无法用函数/方法描述的特征(这里我指的是英语中的"特征",它是"特征"的同义词).通过这种方式,其他人(特别是这些类型的消费者)知道如何正确处理这些类型.例如,Copy是一个标记性状.当将一个类型标记为Copy时,Rust编译器知道当为该类型处理a = b时,它应该执行按位复制.Send也是一个标记性状.在标记时,编译器知道此类型可以被发送到另一个线程.

回到Pod美元.如果我声明我的类型是Pod,为什么我至少要把我的类型变成Copy?当我将我的类型标记为Pod时,我对bytemuck说:"嘿,我的类型是Pod.毫无疑问,你可以相信我.我的类型绝对是Pod.你现在可以将一些字节重新解释为我的类型."

是因为bytemuck希望确保任何包含非Copy类型的类型都不能被标记为Pod吗?因为"A类型是Copy"确实是"A类型是Pod"的necessary but not sufficient condition(毕竟,如果一个类型甚至不是Copy,那么它怎么可能是普通的旧数据).例如,通过这种方式,开发人员不会意外地在定制 struct 中包含非Copy类型(如Vec<u8>String).

如果这真的是原因,我还是很困惑.我仍然需要将一个非常大的字体标记为Copy,才能将其标记为Pod.下面的 struct 是一个示例.

struct MyStruct {
    data: [u8; 10_000_000],
}

这有点荒谬.如果我意外地触发了此类型的按位复制,该怎么办?

不把Copy作为Pod的超级性状难道不是更好的主意吗?我(作为代码作者)将对我标记为Pod的每一种类型承担全部责任.

推荐答案

我不熟悉bytemuck‘S的内部 struct ,但我猜这是一个可靠的要求,因为bytemuck肯定与unsafe代码一起工作来执行位摆弄.

Copy特性的实际规范是,如果值x: T只"拥有它的位",则类型T可以是Copy(就像在Rust的所有权系统中一样).例如,一个整数是Copy,因为当你拥有一个整数时,你只拥有表示这个整数的位,而当你拥有一个Box<i32>时,你不仅仅拥有用于表示盒子的位(这最终只是一个指针).你也拥有指针所指向的东西.

成为Copy的必然结果是,任何Copy类型的值都是移动它与将其clone相加的操作(这就是为什么CloneCopy的超级性状).这是因为在Rust中移动值被定义为基础表示的位的逐位复制,从一个位置到另一个位置.

特别是,如果类型不是Copy,就不能按位复制:every value can be implicitely bitwise-copied whenever it is moved,这是不正确的.因此,如果您的类型是一大块数据,而不是Copy,那么not就可以防止它被逐位复制.

然而,确实预计Copy个类型的复制成本很低,因为除此之外,Rust更喜欢用户必须显式地编写clone,以确保他们有意识地知道他们正在进行一项昂贵的操作.

出于这个原因,您可能确实不想将您的类型标记为Copy.要解决这个问题,您可以使用Newtype模式:创建一个类型struct MyPublicStructure(MyStructure),它执行not实现Copy.实现内部类型的CopyPod.然后,当您需要进行一些位小提琴操作时,只需使用该类型,当您不再需要进行位小提琴操作时,可以将其转换回MyPublicStructure.这样,您可以显式地突出显示代码中需要注意的部分,以免意外地隐式执行昂贵的复制,并且您的公共API是干净的.

Rust相关问答推荐

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

当rust中不存在文件或目录时,std::FS::File::Create().unwire()会抛出错误

如何使用 list 在Rust for Windows中编译?

在Rust中宏的表达式中提取对象

如何循环遍历0..V.len()-1何时v可能为空?

自定义结果枚举如何支持`?`/`FromResidual`?

在铁 rust 中,如何一次只引用几件事中的一件?

Rust wasm 中的 Closure::new 和 Closure::wrap 有什么区别

Rust:为什么 &str 不使用 Into

我们可以在 Rust 切片中使用步骤吗?

在没有任何同步的情况下以非原子方式更新由宽松原子操作 Select 的值是否安全?

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

由特征键控的不同 struct 的集合

不能将 `*self` borrow 为不可变的,因为它也被borrow 为可变的 - 编译器真的需要如此严格吗?

如何将参数传递给Rust 的线程?

为什么具有 Vec 变体的枚举没有内存开销?

如何将切片推入数组?

类型组的通用枚举

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

为什么我返回的 impl Trait 的生命周期限制在其输入的生命周期内?