生命周期想要做的事:在同一个时刻对内存的访问都是有效的。
这个话可以分为两个方面:
- 内存本身是合法的
- 同一时刻不存在数据竞争。
内存本身还有不合法的?
最典型的几种情况。
- 对空指针的操作。
- 自己定义一个内存地址,当做指针来使用。
- 使用已经被回收的栈地址。
前两者在rust中都被标记为unsafe,是需要警惕的边界。这里就不多谈。我们注重理解第3点,使用已经被回收的栈地址。
fn test() -> &i32 {
let i = 2;
&i
}
在上面这个情况中,我们在函数调用过后,可能中会使用已经被回收的栈地址,这是什么危险的行为,这也被叫做悬垂指针。通常情况下我们不会出现这种错误。我们会出错的是引用满天飞的情况。
fn log(a:&str, b:&str) -> &str {
if a.len() > a.len() {
a
} else {
b
}
}
在这个函数中,我们就需要使用声明周期来应对了。在生命周期中,我们需要两个概念。一个输入生命周期,一个输出生命周期。输入的生命周期中是大于输出生命周期。
我们使用一个例子来理解。
我们在使用log函数的时候。
let s = log(a, b);