以下代码按预期失败:
struct T<'a> {
f: &'a Fn(&'a i32),
}
fn test<'a>(_: &'a i32) {}
fn main() {
let t = T { f: &test };
{
let v = 4;
(t.f)(&v);
}
let v1 = 5;
(t.f)(&v1);
}
出现错误:
error[E0597]: `v` does not live long enough
--> src/main.rs:12:15
|
12 | (t.f)(&v);
| ^^ borrowed value does not live long enough
13 | }
| - `v` dropped here while still borrowed
...
16 | (t.f)(&v1);
| ----- borrow later used here
原因是特征对象在其通用类型上是不变的。结果,在通话期间'a
的{{1}}将不会缩短。我明白了但是,如果我删除以下代码段:
t.f()
代码可以很好地编译,我也明白这一点,因为我认为这是由于非词法生存期所致。
当我借用let v1 = 5;
(t.f)(&v1);
(或其中的某些字段)时,事情变得很有趣。考虑上面代码的稍微修改后的版本:
t
该代码可以编译,但是我不明白为什么!这里借用struct T<'a> {
f: &'a Fn(&'a i32),
i: i32,
}
fn test<'a>(_: &'a i32) {}
fn main() {
let t = T { f: &test, i: 1 };
let n = &t.i;
{
let v = 4;
(t.f)(&v);
}
println!("{:?}", n);
}
,结果借用t.i
并在内部作用域结束后使用。我期望这会因上述编译器错误而失败。
作为对策,以下代码借用了整个t
并无法使用与上面相同的消息进行编译。
t
答案 0 :(得分:0)
实际上,它和其他方法一样工作。
struct T<'a> {
f: &'a Fn(&'a i32),
}
此定义表示f
函数将存在于'a
中,并且它的参数也必须存在'a
中。
将fn main()
的生存期视为'm
,将内部范围的生存期视为'i
。您正在main
中创建结构,因此生命周期将是'm
,除非您进入另一个范围,否则它将在main
中生活。
t.f
的参数是
在'i
中创建。根据定义;论证与
函数必须存在相同的生命周期。但是'm
大于'i
。因此,这是不可接受的。'i
。可以认为f
的生存时间与其参数相等。因此,这确保了定义。如果您按如下所示更改定义,请从参数中删除约束。因此,编译器可以为参数推断适当的生存期,它的生存期可以更长,更长或更短。
//this means your f and it's argument's life time can be different
struct T<'a> {
f: &'a Fn(&i32),
}
所有示例都是有效的。
在这里,您可以在Playground
中找到有效的示例