首页 > 解决方案 > 幻影数据用例

问题描述

我试图理解 rust 中的 phantomData,我有一个 Foo 结构环绕一个原始指针,我告诉编译器 Foo 不能超过 'a,所以我试图防止属性 v 的值在 Foo 之前被删除,但是我发现它不起作用,当可以在 f 之前删除 String 时。我误解了什么吗?

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);

标签: rust

解决方案


从评论中,我认为混淆是由T: 'a终身推断引起的。的含义T: 'a是任何生命周期参数T都与 一样长'a。对于T像这样的类型String,没有生命周期参数,因此对于 include 的任何值都是'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);

推荐阅读