English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
El mecanismo de ciclo de vida de Rust es un mecanismo de gestión de recursos tan importante como el mecanismo de propiedad.
La introducción de este concepto es principalmente para abordar los problemas de gestión de recursos en sistemas de tipos complejos.
La cita es un mecanismo indispensable para manejar tipos complejos, después de todo, los datos de tipos complejos no pueden ser copiados ni calculados fácilmente por el procesador.
La cita a menudo conduce a problemas de gestión de recursos extremadamente complejos, conozcamos primero el concepto de referencia suspendida:
{ let r; { let x = 5; r = &x; } println!("r: {}", r); }
这段代码是不会通过 Rust 编译器的,原因是 r 所引用的值已经在使用之前被释放。
上图中的绿色范围 'a 表示 r 的生命周期,蓝色范围 'b 表示 x 的生命周期。很显然,'b 比 'a 小得多,引用必须在值的生命周期以内才有效。
一直以来我们都在结构体中使用 String 而不用 &str,我们用一个案例解释原因:
fn longer(s1: &'str, s2: &'str) -> &str { if s2.len() > s1.len() { s2 } else { s1 } }
longer 函数取 s1 和 s2 两个字符串切片中较长的一个返回其引用值。但只这段代码不会通过编译,原因是返回值引用可能会返回过期的引用:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); } println!("{} es más largo", r); }
这段程序中虽然经过了比较,但 r 被使用的时候源值 s1 和 s2 都已经失效了。当然我们可以把 r 的使用移到 s1 和 s2 在其生命周期范围内防止这种错误的发生,但对于函数来说,它并不能知道自己以外的地方是什么情况,它为了保障自己传递出去的值是正常的,必选所有权原则消除一切危险,所以 longer 函数并不能通过编译。
生命周期注释是描述引用生命周期的办法。
虽然这样并不能够改变引用的生命周期,但可以在合适的地方声明两个引用的生命周期一致。
生命收起注释用单引号开头,跟着一个小写字母单词:
&i32 // 常规引用 &'a i32 // 含有生命周期注释的引用 &'a mut i32 // 可变型含有生命周期注释的引用
让我们用生命周期注释改造 longer 函数:
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 } else { s1 } }
我们需要用泛型声明来规范生命周期的名称,随后函数返回值的生命周期将与两个参数的生命周期一致,所以在调用时可以这样写:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); println!("{} es más largo", r); } }
以上两段程序结合的运行结果:
ecmascript es más largo
注意:别忘记了自动类型判断的原则。
这是之前留下的疑问,在此解答:
fn main() { struct Str<'a> {} content: &'a str } let s = Str { content: "string_slice" }; println!("s.content = {}", s.content); }
Resultado de la ejecución:
s.content = string_slice
Si hay definiciones de métodos para la estructura Str:
impl<'a> Str<'a> { fn get_content(&self) -> &str { self.content } }
Aquí no hay comentarios de ciclo de vida en el valor de retorno, pero no está de más. Es un problema histórico, ya que en las versiones tempranas de Rust no se admitía la determinación automática de ciclo de vida, y todos los ciclos de vida debían declararse estrictamente, pero la versión principal y estable de Rust ya admite esta función.
Hay un comentario de ciclo de vida especial: 'static. Todos los tipos de datos exactos representados por cadenas constantes entre comillas dobles son &'static str, el ciclo de vida de 'static desde el inicio hasta el final de la ejecución del programa.
use std::fmt::Display; fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str donde T: Display { println!("Anuncio! {}", ann); if x.len() > y.len() { x } else { y } }
Este programa proviene de la Biblia de Rust, es un programa que utiliza simultáneamente generics, traits y el mecanismo de ciclo de vida, no es obligatorio, puede experimentarlo, después de todo, tarde o temprano lo necesitará!