Box, Pile et Tas

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, on explore le concept de boxing, d'allocation sur la pile et d'allocation sur le tas en Rust. Toutes les valeurs en Rust sont par défaut allouées sur la pile, mais elles peuvent être emballées (allouées sur le tas) à l'aide du type Box<T>. Un emballage est un pointeur intelligent vers une valeur allouée sur le tas, et lorsqu'il sort de portée, son destructeur est appelé et la mémoire sur le tas est libérée. Le boxing permet de créer une double indirection et peut être déréférencé à l'aide de l'opérateur *. Le laboratoire fournit des exemples de code et des explications sur la manière dont le boxing fonctionne et sur la façon dont il affecte l'allocation de mémoire sur la pile.

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/DataStructuresandEnumsGroup(["Data Structures and Enums"]) 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/floating_types("Floating-point Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-343181{{"Box, Pile et Tas"}} rust/floating_types -.-> lab-343181{{"Box, Pile et Tas"}} rust/string_type -.-> lab-343181{{"Box, Pile et Tas"}} rust/function_syntax -.-> lab-343181{{"Box, Pile et Tas"}} rust/expressions_statements -.-> lab-343181{{"Box, Pile et Tas"}} rust/method_syntax -.-> lab-343181{{"Box, Pile et Tas"}} rust/operator_overloading -.-> lab-343181{{"Box, Pile et Tas"}} end

Box, pile et tas

Toutes les valeurs en Rust sont par défaut allouées sur la pile. Les valeurs peuvent être « emballées » (allouées sur le tas) en créant un Box<T>. Un emballage est un pointeur intelligent vers une valeur allouée sur le tas de type T. Lorsqu'un emballage sort de portée, son destructeur est appelé, l'objet interne est détruit et la mémoire sur le tas est libérée.

Les valeurs emballées peuvent être déréférencées à l'aide de l'opérateur * ; cela supprime une couche d'indirection.

use std::mem;

#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
struct Point {
    x: f64,
    y: f64,
}

// Un Rectangle peut être spécifié par la position de ses coins supérieur gauche et inférieur droit
// dans l'espace
#[allow(dead_code)]
struct Rectangle {
    top_left: Point,
    bottom_right: Point,
}

fn origin() -> Point {
    Point { x: 0.0, y: 0.0 }
}

fn boxed_origin() -> Box<Point> {
    // Alloue ce point sur le tas et renvoie un pointeur vers lui
    Box::new(Point { x: 0.0, y: 0.0 })
}

fn main() {
    // (toutes les annotations de type sont superflues)
    // Variables allouées sur la pile
    let point: Point = origin();
    let rectangle: Rectangle = Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 }
    };

    // Rectangle alloué sur le tas
    let boxed_rectangle: Box<Rectangle> = Box::new(Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 },
    });

    // La sortie de fonctions peut être emballée
    let boxed_point: Box<Point> = Box::new(origin());

    // Double indirection
    let box_in_a_box: Box<Box<Point>> = Box::new(boxed_origin());

    println!("Point occupe {} octets sur la pile",
             mem::size_of_val(&point));
    println!("Rectangle occupe {} octets sur la pile",
             mem::size_of_val(&rectangle));

    // taille de l'emballage == taille du pointeur
    println!("Point emballé occupe {} octets sur la pile",
             mem::size_of_val(&boxed_point));
    println!("Rectangle emballé occupe {} octets sur la pile",
             mem::size_of_val(&boxed_rectangle));
    println!("Emballage dans un emballage occupe {} octets sur la pile",
             mem::size_of_val(&box_in_a_box));

    // Copie les données contenues dans `boxed_point` dans `unboxed_point`
    let unboxed_point: Point = *boxed_point;
    println!("Point non emballé occupe {} octets sur la pile",
             mem::size_of_val(&unboxed_point));
}

Sommaire

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