Explorer le concept de 'static' en Rust

RustRustBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, nous allons discuter du concept de 'static en Rust.

Note: Si le laboratoire ne spécifie pas de nom de fichier, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser main.rs, le compiler et l'exécuter avec rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/integer_types -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/string_type -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/type_casting -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/function_syntax -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/expressions_statements -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/lifetime_specifiers -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/traits -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} rust/operator_overloading -.-> lab-99211{{"Explorer le concept de 'static' en Rust"}} end

Static

Rust a quelques noms de durée de vie réservés. L'un d'entre eux est 'static. Vous pouvez le rencontrer dans deux situations :

// Une référence avec une durée de vie `'static` :
let s: &'static str = "hello world";

// `'static` en tant que partie d'une contrainte de trait :
fn generic<T>(x: T) where T: 'static {}

Les deux sont liés mais subtilement différents et c'est une source commune de confusion lorsqu'on apprend Rust. Voici quelques exemples pour chaque situation :

Durée de vie de la référence

En tant que durée de vie de référence, 'static indique que les données pointées par la référence existent pour toute la durée de vie du programme exécutant. Elle peut toujours être contraite à une durée de vie plus courte.

Il existe deux façons de créer une variable avec une durée de vie 'static, et les deux sont stockées dans la mémoire exécutable du binaire :

  • Créer une constante avec la déclaration static.
  • Créer une chaîne littérale qui a le type : &'static str.

Voyez l'exemple suivant pour voir chaque méthode en action :

// Créer une constante avec une durée de vie `'static`.
static NUM: i32 = 18;

// Retourne une référence à `NUM` où sa durée de vie `'static`
// est contraite à celle de l'argument d'entrée.
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
    &NUM
}

fn main() {
    {
        // Créer une chaîne littérale et l'afficher :
        let static_string = "I'm in read-only memory";
        println!("static_string: {}", static_string);

        // Lorsque `static_string` sort de portée, la référence
        // ne peut plus être utilisée, mais les données restent dans le binaire.
    }

    {
        // Créer un entier pour utiliser avec `coerce_static` :
        let lifetime_num = 9;

        // Contraindre `NUM` à la durée de vie de `lifetime_num` :
        let coerced_static = coerce_static(&lifetime_num);

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

    println!("NUM: {} reste accessible!", NUM);
}

Contrainte de trait

En tant que contrainte de trait, cela signifie que le type ne contient aucune référence non statique. Par exemple, le récepteur peut conserver le type aussi longtemps qu'il le souhaite et il ne deviendra jamais invalide tant qu'il ne le dépose pas.

Il est important de comprendre que cela signifie que toute donnée possédée passe toujours une contrainte de durée de vie 'static, mais une référence à cette donnée possédée ne le fait généralement pas :

use std::fmt::Debug;

fn print_it( input: impl Debug + 'static ) {
    println!( "'static value passed in is: {:?}", input );
}

fn main() {
    // i est possédé et ne contient pas de références, donc il est `'static` :
    let i = 5;
    print_it(i);

    // Oups, &i n'a que la durée de vie définie par la portée de
    // main(), donc ce n'est pas `'static` :
    print_it(&i);
}

Le compilateur vous dira :

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

Résumé

Félicitations ! Vous avez terminé le laboratoire Static. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.