[英]How exactly does PhantomData work in Rust?
我发现PhantomData
中 PhantomData 的概念相当混乱。 我在基于 FFI 的代码中广泛使用它来限制 object 的生命周期,但我仍然不确定我是否正确执行。
这是我经常最终使用它的人为示例。 例如,我不希望MyStruct
的实例比Context
的实例寿命长:
// FFI declarations and types
mod ffi {
use std::ffi::c_void;
pub type handle_t = *const c_void;
// ...
}
// A wrapper structure for some context created and maintained
// inside the C library
struct Context {
// ...
}
// Handle is only valid as long as the Context is alive.
// Hence, I use the PhantomData marker to constrain its lifetime.
struct MyStruct<'a> {
marker: PhantomData<&'a Context>,
handle: ffi::handle_t,
}
impl<'a> MyStruct<'a> {
fn new(context: &'a Context) -> Self {
let handle: ffi::handle_t = context.new_handle();
MyStruct {
marker: PhantomData,
handle
}
}
}
fn main() {
// Initialize the context somewhere inside the C library
let ctx = Context::new(unsafe {ffi::create_context()});
// Create an instance of MyStruct
let my_struct = MyStruct::new(&ctx);
// ...
}
我不太明白以下内容:
这个marker: PhantomData
的东西,在语法上? 我的意思是,它看起来不像构造函数,我希望它是PhantomData{}
或PhantomData()
之类的东西。
出于生命周期跟踪的目的, PhantomData
甚至关心marker
声明中的实际类型? 我尝试将其更改为PhantomData<&'a usize>
,它仍然有效。
在MyStruct::new()
方法的声明中,如果我忘记为context
参数显式指定'a
生命周期, PhantomData
的魔力就会消失,并且可以在MyStruct
之前删除Context
。 这是相当阴险的; 编译器甚至没有给出警告。 那么它分配给marker
的生命周期是多少,为什么?
与上一个问题相关; 如果有多个输入参考 arguments 可能具有不同的生命周期, PhantomData
如何确定使用哪个生命周期?
这个
marker: PhantomData
的东西,在语法上? 我的意思是,它看起来不像构造函数,我希望它是PhantomData{}
或PhantomData()
之类的东西。
您可以定义一个零字段结构,如下所示:
struct Foo;
并像这样创建它的一个实例:
let foo: Foo = Foo;
类型和值都命名为Foo
。
出于生命周期跟踪的目的,
PhantomData
甚至关心标记声明中的实际类型? 我尝试将其更改为PhantomData<&'a usize>
,它仍然有效。
PhantomData
没有什么特别之处,只是它的类型参数未使用不是错误(参见源代码)。 这个行为是通过#[lang = "phantom_data"]
属性启用的,它只是为此目的在编译器中的一个钩子。
在
MyStruct::new()
方法的声明中,如果我忘记为context
参数显式指定'a
生命周期,PhantomData
的魔力就会消失,并且可以在MyStruct
之前删除Context
。 这是相当阴险的; 编译器甚至没有给出警告。 那么它分配给marker
的生命周期是多少,为什么?
PhantomData
可以让您告诉编译器信息它无法自行推断,因为该信息是关于您不直接使用的类型。 由您为编译器提供正确的信息。
在
MyStruct::new()
方法的声明中,如果我忘记为context
参数显式指定'a
生命周期,PhantomData
的魔力就会消失,并且可以在MyStruct
之前删除Context
。 这是相当阴险的; 编译器甚至没有给出警告。 那么它分配给marker
的生命周期是多少,为什么?
我不完全确定我是否理解这个问题。 PhantomData
不做任何事情——它只是一种向编译器传达您正在以某种方式使用数据的方式,并且准确地表达该信息取决于您。 请注意,即使您错误地表达了约束,如果您也有unsafe
的代码,也只能引入 memory 不安全。 在PhantomData
中正确表达生命周期是围绕不安全代码创建安全抽象的一部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.