为什么不能在结构定义中省略生命周期?
Why can the lifetimes not be elided in a struct definition?
struct Point {
x: u32,
y: u32,
}
struct Line<'a> {
start: &'a Point,
end: &'a Point,
}
此处,start
和 end
字段唯一可能的选择是使生命周期与包含它们的 Line
变量相同或更长。我什至无法想象人们将如何使用生命周期说明符来表示这些字段的生命周期较短。
为什么我必须在这里明确指定生命周期?在这种情况下是否不可能省略?如果可以,为什么不呢?
当你定义一个结构时,你并没有在结构的生命周期和字段的生命周期之间建立关系。正如您所指出的,字段 中的引用 比结构的寿命更长。
相反,您正在做的是提供一个 "generic lifetime",它将在您创建结构时专门化。这类似于具有类型参数的结构:
struct Foo<T>
foo: T,
}
当您构建结构时,编译器将插入适当的生命周期(或类型),然后检查是否一切正常。
另一件事是您可以指定生命周期彼此:
struct Line<'a, 'b: 'a> {
start: &'a Point,
end: &'b Point,
}
这表示 start
和 end
可以有 不同的 生命周期,只要 end
的生命周期比 start
.
的寿命长
why doesn't the compiler do lifetime elision for structs? It seems in the spirit of Rust to do so
(强调我的)
我实际上相信 Rust 倾向于显式,尤其是在定义顶级项目(如函数、结构)时。
函数的生命周期省略规则范围很小,empirically found in RFC 141具有很高的成功率 (87%)。这是一项非常符合人体工程学的投资 return。
也许在某些时候,结构会发生类似的省略,但这还不是一个足够大的问题还。如果您对此有强烈的感觉,那么我强烈建议您在 user forum 上寻求共识,然后进入开发者论坛,然后最终制定一个 RFC。
RFC 2093 添加少量推理。在它实现之前,你必须表达作为引用的泛型类型需要比引用更长久:
struct Foo<'a, T: 'a> {
start: &'a T,
}
在任何情况下你不会想要这个绑定,所以在 RFC 实施后,你可以说:
struct Foo<'a, T> {
start: &'a T,
}
假设我们有一个 Line
的构造函数:
impl<'a> Line<'a> {
fn new(start: &'a Point, end: &'a Point) -> Line<'a> { // '
Line {
start: start,
end: end,
}
}
}
new
return一个Line<'a>
。为了能够用生命周期参数化一个类型(就像我们在这里使用 Line<'a>
所做的那样),这个类型必须定义生命周期参数!尽管编译器 可以 在必要时自动定义生命周期参数,但仅通过查看源代码中的定义就可以更容易地判断一个类型是否具有生命周期参数。
结构和枚举的生命周期参数在借用检查器中起着重要作用。它们让编译器知道结构保留借用某些值。当您尝试改变具有活动借用的值时,编译器可能会 return 错误。
fn main() {
let mut start = Point { x: 2, y: 4 };
let end = Point { x: 7, y: 10 };
let line = Line::new(&start, &end);
start.x = 3; // error: cannot assign to `start.x` because it is borrowed
}
struct Point {
x: u32,
y: u32,
}
struct Line<'a> {
start: &'a Point,
end: &'a Point,
}
此处,start
和 end
字段唯一可能的选择是使生命周期与包含它们的 Line
变量相同或更长。我什至无法想象人们将如何使用生命周期说明符来表示这些字段的生命周期较短。
为什么我必须在这里明确指定生命周期?在这种情况下是否不可能省略?如果可以,为什么不呢?
当你定义一个结构时,你并没有在结构的生命周期和字段的生命周期之间建立关系。正如您所指出的,字段 中的引用 比结构的寿命更长。
相反,您正在做的是提供一个 "generic lifetime",它将在您创建结构时专门化。这类似于具有类型参数的结构:
struct Foo<T>
foo: T,
}
当您构建结构时,编译器将插入适当的生命周期(或类型),然后检查是否一切正常。
另一件事是您可以指定生命周期彼此:
struct Line<'a, 'b: 'a> {
start: &'a Point,
end: &'b Point,
}
这表示 start
和 end
可以有 不同的 生命周期,只要 end
的生命周期比 start
.
why doesn't the compiler do lifetime elision for structs? It seems in the spirit of Rust to do so
(强调我的)
我实际上相信 Rust 倾向于显式,尤其是在定义顶级项目(如函数、结构)时。
函数的生命周期省略规则范围很小,empirically found in RFC 141具有很高的成功率 (87%)。这是一项非常符合人体工程学的投资 return。
也许在某些时候,结构会发生类似的省略,但这还不是一个足够大的问题还。如果您对此有强烈的感觉,那么我强烈建议您在 user forum 上寻求共识,然后进入开发者论坛,然后最终制定一个 RFC。
RFC 2093 添加少量推理。在它实现之前,你必须表达作为引用的泛型类型需要比引用更长久:
struct Foo<'a, T: 'a> {
start: &'a T,
}
在任何情况下你不会想要这个绑定,所以在 RFC 实施后,你可以说:
struct Foo<'a, T> {
start: &'a T,
}
假设我们有一个 Line
的构造函数:
impl<'a> Line<'a> {
fn new(start: &'a Point, end: &'a Point) -> Line<'a> { // '
Line {
start: start,
end: end,
}
}
}
new
return一个Line<'a>
。为了能够用生命周期参数化一个类型(就像我们在这里使用 Line<'a>
所做的那样),这个类型必须定义生命周期参数!尽管编译器 可以 在必要时自动定义生命周期参数,但仅通过查看源代码中的定义就可以更容易地判断一个类型是否具有生命周期参数。
结构和枚举的生命周期参数在借用检查器中起着重要作用。它们让编译器知道结构保留借用某些值。当您尝试改变具有活动借用的值时,编译器可能会 return 错误。
fn main() {
let mut start = Point { x: 2, y: 4 };
let end = Point { x: 7, y: 10 };
let line = Line::new(&start, &end);
start.x = 3; // error: cannot assign to `start.x` because it is borrowed
}