Box<T>

Box 是具有所有權的指向堆積上的資料的指標:

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

Box<T> 會實作 Deref<Target = T>。也就是說,您可以直接在 Box<T> 上透過 T 呼叫方法

遞迴資料型別或含有動態大小的資料型別必須使用 Box

#[derive(Debug)]
enum List<T> {
    /// A non-empty list: first element and the rest of the list.
    Element(T, Box<List<T>>),
    /// An empty list.
    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 is like std::unique_ptr in C++, except that it's guaranteed to be not null.

  • 在以下情況下,您可以使用 Box

    • 編譯時遇到不知道大小為何的型別,但 Rust 編譯器需要知道確切大小。
    • 想要轉移大量資料的所有權。為避免在堆疊上複製大量資料,請改將資料儲存在 Box 的堆積上,這樣系統就只會移動指標。
  • If Box was not used and we attempted to embed a List directly into the List, the compiler would not be able to compute a fixed size for the struct in memory (the List would be of infinite size).

  • Box 大小與一般指標相同,並且只會指向堆積中的下一個 List 元素,因此可以解決這個問題。

  • Remove the Box in the List definition and show the compiler error. We get the message "recursive without indirection", because for data recursion, we have to use indirection, a Box or reference of some kind, instead of storing the value directly.

探索更多內容

區位最佳化

#[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:?}");
}

Box 不能空白,因此指標會一律有效,而且不會是 null。這樣一來,編譯器可以將記憶體配置最佳化:

StackHeaplistElement1Element2