静态 - Rust By Example
Description: Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# 静态

Rust 有几个保留的生命周期名称。其中之一是 `'static`。你可能在两种情况下遇到它：

    // 具有 'static 生命周期的引用：
    let s: &'static str = "你好，世界";

    // 'static 作为 trait 约束的一部分：
    fn generic<T>(x: T) where T: 'static {}

这两种情况虽然相关但有微妙的区别，这也是学习 Rust 时常见的困惑来源。以下是每种情况的一些例子：

## 引用生命周期

作为引用生命周期，`'static` 表示该引用指向的数据在程序的整个剩余运行期间都有效。它仍然可以被强制转换为更短的生命周期。

有两种常见的方法可以创建具有 `'static` 生命周期的变量，它们都存储在二进制文件的只读内存中：

- 使用 `static` 声明创建一个常量。
- 创建一个字符串字面量，其类型为：`&'static str`。

请看下面的例子，展示了这些方法：

    // 创建一个具有 `'static` 生命周期的常量。
    static NUM: i32 = 18;

    // 返回一个指向 `NUM` 的引用，其中 `'static` 生命周期
    // 被强制转换为输入参数的生命周期。
    fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
        &NUM
    }

    fn main() {
        {
            // 创建一个字符串字面量并打印它：
            let static_string = "我存储在只读内存中";
            println!("static_string 的值：{}", static_string);

            // 当 `static_string` 离开作用域时，该引用
            // 不能再被使用，但数据仍然保留在二进制文件中。
        }

        {
            // 创建一个整数用于 `coerce_static` 函数：
            let lifetime_num = 9;

            // 将 `NUM` 的生命周期强制转换为与 `lifetime_num` 一致：
            let coerced_static = coerce_static(&lifetime_num);

            println!("coerced_static: {}", coerced_static);
        }

        println!("NUM：{} 仍然可以访问！", 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 约束

作为 trait 约束时，它表示该类型不包含任何非静态引用。例如，接收者可以随意持有该类型，直到主动丢弃之前，它都不会变为无效。

理解这一点很重要：任何拥有所有权的数据总是满足 `'static` 生命周期约束，但对该数据的引用通常不满足：

    use std::fmt::Debug;

    fn print_it(input: impl Debug + 'static) {
        println!("传入的 'static 值是：{:?}", input);
    }

    fn main() {
        // i 拥有所有权且不包含任何引用，因此它是 'static 的：
        let i = 5;
        print_it(i);

        // 糟糕，&i 的生命周期仅由 main() 的作用域定义，
        // 所以它不是 '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` 常量