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

Box<T>

Box — владеющий указатель на данные в куче:

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

fn main() {
    let five = Box::new(5);
    println!("five: {}", *five);
}
5StackHeapfive

Box<T> реализует Deref<Target = T>, что означает, что можно вызывать методы T напрямую на Box<T>.

Рекурсивные типы данных и типы данных с динамическим размером нельзя хранить напрямую без косвенности через указатель. Box обеспечивает эту косвенность:

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug)]
enum List<T> {
    /// Непустой список: первый элемент и остальная часть списка.
    Element(T, Box<List<T>>),
    /// Пустой список.
    Nil,
}

fn main() {
    let list: List<i32> =
        List::Element(1, Box::new(List::Element(2, Box::new(List::Nil))));
    println!("{list:?}");
}
StackHeaplistElement1Element2Nil
This slide should take about 8 minutes.
  • Box похож на std::unique_ptr в C++, но гарантирует, что он не будет нулевым (null).

  • Box может быть полезен, когда вы:

    • имеете тип, размер которого нельзя узнать во время компиляции, но компилятору Rust нужен точный размер.
    • хотите передать владение большим объёмом данных. Чтобы не копировать большой объём данных на стеке, сохраните данные в куче в Box: тогда перемещается только указатель.
  • Если бы Box не использовался и мы попытались бы встроить List прямо в List, компилятор не смог бы вычислить фиксированный размер структуры в памяти (List был бы бесконечного размера).

  • Box решает эту проблему: он имеет тот же размер, что и обычный указатель, и просто указывает на следующий элемент List в куче.

  • Уберите Box из определения List и покажите ошибку компилятора. Мы получим сообщение «recursive without indirection», потому что для рекурсивных данных нужна косвенность — Box или ссылка какого-то вида, — а не прямое хранение значения.

  • Хотя Box выглядит как std::unique_ptr в C++, он не может быть пустым (null). Это делает Box одним из типов, которые позволяют компилятору оптимизировать хранение некоторых перечислений («оптимизация ниш»).