作为 Rust 的新手,我的理解是显式生命周期有两个作用。
1. 在函数上放置显式生命周期注释会限制可能出现在该函数内的代码类型。显式生命周期允许编译器确保您的程序正在执行您想要的操作。
2. 如果您(编译器)想要检查代码片段是否有效,则不必迭代查看每个被调用的函数内部。只需查看由该代码片段直接调用的函数的注释即可。这使得您(编译器)更容易推理您的程序,并使编译时间可管理。
关于第一点,请考虑以下用 Python 编写的程序:
import pandas as pd
import numpy as np
def second_row(ar):
return ar[0]
def work(second):
df = pd.DataFrame(data=second)
df.loc[0, 0] = 1
def main():
ar = np.array([[0, 0], [0, 0]])
second = second_row(ar)
work(second)
print(repr(ar))
if __name__=="__main__":
main()
这将打印输出
array([[1, 0],
[0, 0]])
这种行为总是让我感到惊讶。发生的情况是
df
与
ar
共享内存,因此当
df
中的某些内容在
work
中发生更改时,该更改也会影响
ar
。但是,在某些情况下,出于内存效率的原因(不需要复制),这可能正是您想要的。这段代码中真正的问题是函数
second_row
返回的是第一行而不是第二行。祝你好运调试。
考虑一个用Rust编写的类似程序:
#[derive(Debug)]
struct Array<'a, 'b>(&'a mut [i32], &'b mut [i32]);
impl<'a, 'b> Array<'a, 'b> {
fn second_row(&mut self) -> &mut &'b mut [i32] {
&mut self.0
}
}
fn work(second: &mut [i32]) {
second[0] = 1;
}
fn main() {
let ar1 = &mut [0, 0][..];
let ar2 = &mut [0, 0][..];
let mut ar = Array(ar1, ar2);
{
let second = ar.second_row();
work(second);
}
println!("{:?}", ar);
}
编译这个程序之后,您会得到以下结果。
error[E0308]: mismatched types
--> src/main.rs:6:13
|
6 | &mut self.0
| ^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `&mut &'b mut [i32]`
found type `&mut &'a mut [i32]`
note: the lifetime 'b as defined on the impl at 4:5...
--> src/main.rs:4:5
|
4 | impl<'a, 'b> Array<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 4:5
--> src/main.rs:4:5
|
4 | impl<'a, 'b> Array<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
实际上,您会得到两个错误,其中一个是交换了 'a 和 'b 的角色。查看 second_row 的注释,我们发现输出应该是 &mut &'b mut [i32],也就是说,输出应该是一个具有 'b 生命周期(Array 的第二行的生命周期)的引用的引用。然而,因为我们返回的是第一行(它的生命周期是 'a),编译器抱怨生命周期不匹配。在正确的地方。在正确的时间。调试是轻松愉快的。