我正在查看一些Rust源代码,发现了一个叫做 PhantomData
的数据类型。我翻阅了 Rust 文档并通过互联网进行了搜索,但是我无法理解这个数据类型在 Rust 中的实际用途。如果可能的话,请有经验的人给我简单地解释一下。
pub struct GPIOD {
_marker: PhantomData<*const ()>,
}
我正在查看一些Rust源代码,发现了一个叫做 PhantomData
的数据类型。我翻阅了 Rust 文档并通过互联网进行了搜索,但是我无法理解这个数据类型在 Rust 中的实际用途。如果可能的话,请有经验的人给我简单地解释一下。
pub struct GPIOD {
_marker: PhantomData<*const ()>,
}
PhantomData
结构体用于向编译器表明类型或生命周期被以对编译器透明的方式使用。
引用文档:
在类型中添加
PhantomData
字段,告诉编译器您的类型表现得像存储了类型T
的值一样,即使实际上并没有。这些信息在计算某些安全性属性时使用。
例如,如果我们查看切片[T]
的迭代器类型:std::slice::Iter<'a, T>
和使用src按钮进行声明,我们会发现它实际上是这样声明的:
struct Iter<'a, T: 'a> {
start: *const T,
end: *const T,
_phantom: PhantomData<&'a T>,
}
std
经常使用指针算术以便更容易地进行优化 (虽然这并不是为了支持在用户代码中使用指针算术)。在这种情况下,我们需要确保被这两个裸指针(不带有生命周期)所指向的数据比结构体的生命周期更长,因此我们保留一个PhantomData<&'a T>
,告诉编译器像 Iter
拥有一个 &'a T
一样,从而强制执行其生命周期规则。
PhantomData
允许在两个结构体之间添加任意的生命周期依赖关系。struct LogManager {
// ...
}
impl LogManager {
fn logger(&self) -> Logger {
// returns a fresh `Logger` that holds no reference to `LogManager`...
}
}
struct Logger {
// ...
}
Logger
持有幽灵引用,我们可以在这2个结构之间强制建立依赖关系:struct Logger<'a> {
// ...
_marker: PhantomData<'a ()>,
}
并且在实现块中:
impl LogManager {
fn logger(&self) -> Logger {
Logger {
// ...
// Here, `Logger` will have a lifetime dependent of the `LogManager`'s
// lifetime due to `PhantomData`:
_marker: PhantomData,
}
}
}
Logger
的实例都不能超过它所属的LogManager
。
svd2rust
自动生成的 HAL crate 吗? - Sébastien Renauld