Box, Pila y Montón

Beginner

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

Introducción

En este laboratorio, se explora el concepto de boxing, asignación en pila y asignación en el montón en Rust. Todos los valores en Rust se asignan en pila por defecto, pero se pueden empaquetar (asignar en el montón) utilizando el tipo Box<T>. Una caja es un puntero inteligente a un valor asignado en el montón, y cuando sale del ámbito, se llama a su destructor y se libera la memoria en el montón. El boxing permite la creación de doble indirección y se puede desreferenciar utilizando el operador *. El laboratorio proporciona ejemplos de código y explicaciones de cómo funciona el boxing y cómo afecta a la asignación de memoria en la pila.

Nota: Si el laboratorio no especifica un nombre de archivo, puede utilizar cualquier nombre de archivo que desee. Por ejemplo, puede utilizar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.

Box, pila y montón

Todos los valores en Rust se asignan en pila por defecto. Los valores se pueden "empaquetar" (asignar en el montón) creando un Box<T>. Una caja es un puntero inteligente a un valor de tipo T asignado en el montón. Cuando una caja sale del ámbito, se llama a su destructor, el objeto interno se destruye y se libera la memoria en el montón.

Los valores empaquetados se pueden desreferenciar utilizando el operador *; esto quita un nivel de indirección.

use std::mem;

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

// Un Rectángulo se puede especificar por donde están sus esquinas superior izquierda e inferior derecha
// en el espacio
#[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> {
    // Asigna este punto en el montón y devuelve un puntero a él
    Box::new(Point { x: 0.0, y: 0.0 })
}

fn main() {
    // (todas las anotaciones de tipo son superfluas)
    // Variables asignadas en pila
    let point: Point = origin();
    let rectangle: Rectangle = Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 }
    };

    // Rectángulo asignado en el montón
    let boxed_rectangle: Box<Rectangle> = Box::new(Rectangle {
        top_left: origin(),
        bottom_right: Point { x: 3.0, y: -4.0 },
    });

    // La salida de funciones se puede empaquetar
    let boxed_point: Box<Point> = Box::new(origin());

    // Doble indirección
    let box_in_a_box: Box<Box<Point>> = Box::new(boxed_origin());

    println!("Point ocupa {} bytes en la pila",
             mem::size_of_val(&point));
    println!("Rectangle ocupa {} bytes en la pila",
             mem::size_of_val(&rectangle));

    // Tamaño de la caja == tamaño del puntero
    println!("Boxed point ocupa {} bytes en la pila",
             mem::size_of_val(&boxed_point));
    println!("Boxed rectangle ocupa {} bytes en la pila",
             mem::size_of_val(&boxed_rectangle));
    println!("Boxed box ocupa {} bytes en la pila",
             mem::size_of_val(&box_in_a_box));

    // Copia los datos contenidos en `boxed_point` en `unboxed_point`
    let unboxed_point: Point = *boxed_point;
    println!("Unboxed point ocupa {} bytes en la pila",
             mem::size_of_val(&unboxed_point));
}

Resumen

¡Felicidades! Has completado el laboratorio de Box, Pila y Montón. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.