静态
Rust 有一些保留的生命周期名称。其中之一是 'static
。你可能会在两种情况下遇到它
// A reference with 'static lifetime: let s: &'static str = "hello world"; // 'static as part of a trait bound: fn generic<T>(x: T) where T: 'static {}
两者相关但又略有不同,这是学习 Rust 时常见的混淆来源。以下是每种情况的一些示例
引用生命周期
作为引用生命周期,'static
表示引用指向的数据在程序运行的剩余生命周期内都存在。它仍然可以被强制转换为较短的生命周期。
有两种常见的方法可以创建具有 'static
生命周期变量,它们都存储在二进制文件的只读内存中
- 使用
static
声明创建一个常量。 - 创建一个类型为
&'static str
的string
字面量。
请参阅以下示例,了解每种方法的展示
// Make a constant with `'static` lifetime. static NUM: i32 = 18; // Returns a reference to `NUM` where its `'static` // lifetime is coerced to that of the input argument. fn coerce_static<'a>(_: &'a i32) -> &'a i32 { &NUM } fn main() { { // Make a `string` literal and print it: let static_string = "I'm in read-only memory"; println!("static_string: {}", static_string); // When `static_string` goes out of scope, the reference // can no longer be used, but the data remains in the binary. } { // Make an integer to use for `coerce_static`: let lifetime_num = 9; // Coerce `NUM` to lifetime of `lifetime_num`: let coerced_static = coerce_static(&lifetime_num); println!("coerced_static: {}", coerced_static); } println!("NUM: {} stays accessible!", NUM); }
由于 'static
引用只需要在程序的剩余生命周期内有效,它们可以在程序执行时创建。为了演示,以下示例使用 Box::leak
来动态创建 'static
引用。在这种情况下,它肯定不会在整个持续时间内存在,而只是从泄露点开始存在。
extern crate rand; use rand::Fill; fn random_vec() -> &'static [usize; 100] { let mut rng = rand::thread_rng(); let mut boxed = Box::new([0; 100]); boxed.try_fill(&mut rng).unwrap(); Box::leak(boxed) } fn main() { let first: &'static [usize; 100] = random_vec(); let second: &'static [usize; 100] = random_vec(); assert_ne!(first, second) }
Trait bound (特征约束)
作为 trait bound,它意味着该类型不包含任何非静态引用。例如,接收者可以保持该类型,只要他们想保持,它都不会失效,直到他们将其丢弃。
重要的是要理解,这意味着任何拥有的数据始终通过 'static
生命周期绑定,但对该拥有数据的引用通常不会。
use std::fmt::Debug; fn print_it( input: impl Debug + 'static ) { println!( "'static value passed in is: {:?}", input ); } fn main() { // i is owned and contains no references, thus it's 'static: let i = 5; print_it(i); // oops, &i only has the lifetime defined by the scope of // main(), so it's not 'static: print_it(&i); }
编译器会告诉你
error[E0597]: `i` does not live long enough
--> src/lib.rs:15:15
|
15 | print_it(&i);
| ---------^^--
| | |
| | borrowed value does not live long enough
| argument requires that `i` is borrowed for `'static`
16 | }
| - `i` dropped here while still borrowed