PhantomData用例
我试图在 rust 中理解 phantomData,我有一个 Foo struct 环绕一个原始指针,我告诉编译器 Foo 不能活过 'a,所以我试图防止属性 v 的值在 Foo 之前被删除,但是我发现它不起作用,当 String s 可以在 f 之前被删除时。我是不是误会了什么?
struct Foo<'a, T: 'a> { // I say that T is valid over lifetime 'a
pub v: *mut T,
_mark: PhantomData<&'a T>
}
fn main() {
let mut s = String::from("hello");
let f = Foo {
v: &mut s,
_mark: PhantomData,
};
drop(s);
drop(f);
}
我发现我什至可以在像这样删除 s 之后使用指向 s 的指针
let mut s = String::from("hello");
let f = Foo {
v: &mut s,
_mark: PhantomData,
};
drop(s);
let a = unsafe {&*f.v};
println!("{}", a);
回答
从评论中,我认为混淆是由T: 'a终生推理引起的。的含义T: 'a是 的任何生命周期参数T都与 一样长'a。对于T像 那样的类型String,没有生命周期参数,因此对于'a包括的任何值都是如此'static。
粗略地说,这T: 'a意味着T只要'a. 它必须拥有自己的数据(如String),或者它包含的任何引用都必须存在足够长的时间。
因此,当您初始化时f:
let f = Foo {
v: &mut s,
_mark: PhantomData,
};
T可以推断为String,但 的任何值'a都是有效的。寿命没有限制。
必须以某种方式告诉编译器初始化引用的生命周期(我们在初始化之前将其转换为无生命周期的指针Foo)与我们想要在 上使用的生命周期相关联Foo。例如:
impl<'a, T: 'a> Foo<'a, T> {
// the input lifetime and the output lifetime are the same
fn new(t: &'a mut T) -> Foo<'a, T> {
Foo {
v: t,
_mark: PhantomData,
}
}
}
let f = Foo::new(&mut s);