Box, Stack e Heap

Beginner

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

Introdução

Neste laboratório, o conceito de boxing, alocação na stack (pilha) e alocação na heap (heap) em Rust é explorado. Todos os valores em Rust são alocados na stack por padrão, mas podem ser boxed (alocados na heap) usando o tipo Box<T>. Um box é um smart pointer (ponteiro inteligente) para um valor alocado na heap, e quando ele sai do escopo, seu destrutor é chamado e a memória na heap é liberada. O boxing permite a criação de dupla indireção e pode ser desreferenciado usando o operador *. O laboratório fornece exemplos de código e explicações de como o boxing funciona e como ele afeta a alocação de memória na stack.

Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar main.rs, compilar e executá-lo com rustc main.rs && ./main.

Box, stack e heap

Todos os valores em Rust são alocados na stack por padrão. Os valores podem ser boxed (alocados na heap) criando um Box<T>. Um box é um smart pointer para um valor alocado na heap do tipo T. Quando um box sai do escopo, seu destrutor é chamado, o objeto interno é destruído e a memória na heap é liberada.

Valores boxed podem ser desreferenciados usando o operador *; isso remove uma camada de indireção.

use std::mem;

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

// A Rectangle can be specified by where its top left and bottom right
// corners are in space
#[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> {
    // Allocate this point on the heap, and return a pointer to it
    Box::new(Point { x: 0.0, y: 0.0 })
}

fn main() {
    // (all the type annotations are superfluous)
    // Stack allocated variables
    let point: Point = origin();
    let rectangle: Rectangle = Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 }
    };

    // Heap allocated rectangle
    let boxed_rectangle: Box<Rectangle> = Box::new(Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 },
    });

    // The output of functions can be boxed
    let boxed_point: Box<Point> = Box::new(origin());

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

    println!("Point occupies {} bytes on the stack",
             mem::size_of_val(&point));
    println!("Rectangle occupies {} bytes on the stack",
             mem::size_of_val(&rectangle));

    // box size == pointer size
    println!("Boxed point occupies {} bytes on the stack",
             mem::size_of_val(&boxed_point));
    println!("Boxed rectangle occupies {} bytes on the stack",
             mem::size_of_val(&boxed_rectangle));
    println!("Boxed box occupies {} bytes on the stack",
             mem::size_of_val(&box_in_a_box));

    // Copy the data contained in `boxed_point` into `unboxed_point`
    let unboxed_point: Point = *boxed_point;
    println!("Unboxed point occupies {} bytes on the stack",
             mem::size_of_val(&unboxed_point));
}

Resumo

Parabéns! Você concluiu o laboratório Box, Stack e Heap. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.