rust - 幻影数据用例
问题描述
我试图理解 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);
解决方案
从评论中,我认为混淆是由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);
推荐阅读
- sql - 在编写具有多个连接的查询时遇到问题
- c - 正确使用 strcpy() 并避免 valgrind 中的读写大小错误
- gerrit - 在 Gerrit 中,如何将任意标签推送到非标准位置?
- c++ - 在 C++ 中做一个场景问题并且不确定如何进行布尔和 if 循环
- elixir - Ecto ILIKE 用于多个关键字?
- javascript - 如果在 3 秒内没有发生 keydown 事件,JavaScript 会显示文本?
- database - 如何将旧的 magento(2.1.5) 数据库迁移到新的 magento2.3.3
- python-3.x - 分段函数
- regex - 正面展望案例
- c++ - C++ 段错误,可重现的示例