静态

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 strstring 字面量。

请参阅以下示例以了解每种方法的显示方式

// 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)
}

特征约束

作为特征约束,它表示该类型不包含任何非静态引用。例如,接收者可以根据需要持有该类型,并且它永远不会失效,直到他们丢弃它。

重要的是要理解,这意味着任何拥有的数据总是传递 '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

另请参阅

'static 常量