为什么这段代码会编译?
#[derive(Debug)]
pub struct Foo<'a> {
pub x: &'a [&'a str],
}
fn main() {
let s = "s".to_string();
let t: &str = s.as_ref();
{
let v = vec![t];
let foo = Foo { x: &v[..] };
println!("{:?}", &foo);
}
}
在我的Foo
结构中,我的x
字段包含一片&strs
。我对这些生命周期标签的理解是切片和个体&strs
具有相同的生命周期。
但是,在我的示例中,&str
t
(在外部块中)与容器切片的生命周期不同(在内部块中)。
答案 0 :(得分:6)
我对这些生命周期标签的理解是切片和个人
&strs
具有相同的生命周期。
这是一种常见的误解。这实际上意味着必须存在适用于两者的 a 生命周期。实例化时,Foo
结构的'a
对应于let v = vec![t];
之后的内部块的行,因为这是两个变量共享的生命周期。
如果不存在这种灵活性,使用寿命会非常痛苦。在两条线上定义的变量具有不同的实际寿命(首先定义的变量超过定义的第二个)。如果生命周期必须实际匹配,我们总是必须在同一行上定义所有变量!
RFC #738 — Variance中提供了一些更详细的信息。
答案 1 :(得分:2)
语法'a
实际上用于两种不同的情况:
第一种情况,标记循环:
fn main() {
'a: loop {
println!("{}", 3);
break 'a;
}
}
在这里,'a
清楚地描述了循环体的寿命,并允许一举破坏多层循环。
第二种更类似的情况是使用'a
来表示绑定:
fn<'a> susbtr(haystack: &'a str, offset: usize) -> &'a str;
在这种情况下,生命周期'a
不代表变量的实际生命周期,它表示引用变量生命周期中的绑定,并允许绑在一起< / em>各种变量的界限。
请注意,调用者和被调用者以不同方式解释绑定:
'a
是一个上限,一个承诺,返回值将至少与参数一样长 (可能更长,不保证)substr
),'a
是下限,检查任何返回的值必须至少 作为参数(可能更长,没必要)我们可以有方差,因为绑定不代表实际生命周期,当单个绑定用于多个生命周期时,编译器将简单地推导出对该情况有意义的最低/最高边界:
例如:
fn<'b> either(one: &'b str, two: &'b str, flag: bool) -> &'b str {
if flag { one } else { two }
}
可以通过以下方式调用:
fn<'a> call(o: &'a str, flag: bool) -> &'a str {
either(o, "Hello, World", flag)
}
此处,o
的生命周期未知(某些'a
),而"Hello, World"
的生命周期已知('static
),'static
按定义生命周期越长(它适用于所有程序)。
call
的来电者只知道返回值的有效期至少与o
call
必须保证这一点,它会向o
提供"Hello, World"
和either
,其中'b
被推断为'a
之间的最低界限和'static
(因此'a
)either
只需返回与其中任何一个论点一样长的东西;它没有意识到他们的生命可能会有所不同,并且不在乎