rust - 如何理解 Rust 中函数参数和返回值的生命周期?
问题描述
我是 Rust 的新手,我仍然在 Rust 中挣扎。Rust 编程语言书将生命周期定义为
该引用有效的范围
当上下文是单个函数时,很容易理解。例如,在下面的代码中,s 的生命周期是蓝色框,x 的生命周期是绿色框等。
说到函数,我不太明白函数参数和返回值的生命周期到底意味着什么。假设我们有这个功能:
fn parse_record<'i>(input: &'i [u8]) -> Record<'i> { ... }
签名声明input
参数和返回值Record
必须具有相同的生命周期'i
。这是否意味着当我们调用函数时,我们传递给函数的值和返回的值必须具有相同的生命周期?例如,我可以main
像这样调用函数中的函数:
fn main() {
let mut v: Vec<u8> = [1_u8, 2_u8, 3_u8].to_vec();
let result = parse_record(&v);
// use v and result ...
}
函数签名中的生命周期是否表明v
和result
inmain
必须具有相同的生命周期?
解决方案
我想在这里澄清一下,引用Rust by Example
生命周期是编译器(或更具体地说,它的借用检查器)用来确保所有借用有效的构造。具体来说,变量的生命周期从创建时开始,到销毁时结束。虽然生命周期和作用域经常一起被提及,但它们并不相同。
举个例子,我们通过 & 借用一个变量。借用的生命周期取决于它的声明位置。因此,只要在贷方被销毁之前结束,借入就有效。但是,借用的范围取决于使用引用的位置。
似乎 Rust 书造成了很多混乱,但当我们谈论拥有数据(而不是借用它)生命周期和范围匹配的简单绑定时,确实是不同的东西scope
。lifetime
如果我们有这样的简单代码。的生命周期a
并将b
与它们定义的范围相匹配。
fn main() {
let a = 1;
let b = 2;
}
在此示例中,贷方 ( a
) 比借用更早地超出范围。
fn main() {
let b;
{
let a = 1;
b = &a;
}
let c = *b;
}
它强制编译器发出错误。
error[E0597]: `a` does not live long enough
--> src/main.rs:5:9
|
5 | b = &a;
| ^^^^^^ borrowed value does not live long enough
6 | }
| - `a` dropped here while still borrowed
7 | let c = *b;
| -- borrow later used here
所以 hereb
的生命周期比 的生命周期长a
,因为它的作用域更大。请记住,借用范围取决于引用的使用位置。
但是这段代码编译得很好,因为范围在被删除b
后并没有结束。a
fn main() {
let b;
{
let a = 1;
b = &a;
let c = *b;
}
}
要澄清的另一件事是引用&'lifetime
手段的生命周期语法。这意味着引用应该与'lifetime
生命周期一样长。不应该是那样的一生。
假设Record
元素是这样定义的。
struct Record<'a> {
some_member: &'a Type
}
此签名仅意味着某些记录成员应与传递给的引用一样长,input
反之亦然。
fn parse_record<'i>(input: &'i [u8]) -> Record<'i> { ... }
如果我把它翻译成简单的英语。只要内部的字段Record
没有超出范围,传递给函数的引用的贷方就不应超出范围(丢弃)。
或者函数的返回值应该与函数的输入参数一样长。
如果我们没有受输入生命周期约束的返回值,则翻译会发生变化。
fn test<'a>(a: &'a i32, b: &'a i32)
这意味着在函数执行结束之前,贷方a
和贷方b
应该在范围内。
在许多简单的情况下,编译器会忽略生命周期,您不必担心它们。实际上,在您的示例中,也可以省略生命周期。
fn parse_record(input: &[u8]) -> Record { ... }
我建议您阅读Rust by Example
有关生命的章节以更实际地理解它们。
推荐阅读
- html - 即使在 Bootstrap Grid Columns 丢失的情况下也可以向右拉
- python - 从被测方法中导入的模块中修补方法
- bytecode - 为什么字节码序列号不连续
- c - C 接受关于传递关系的输入
- javascript - 解析etherscan
- java - 如何在没有触摸 xml 的情况下在休眠中处理延迟初始化异常
- jquery - 更改月份时,防止 Fullcalendar 为同一元素添加新的单击事件处理程序
- angular - 如何在 Typescript(Angular Material)中实现回调函数?
- java - 如何为 ScheduledThreadPoolExecutor 类设置 maxPool 大小和 keepAliveTime?
- python - importError python while import 存在并且Pycharm识别它