Box<T>
Box
是具有所有權的指向堆積上的資料的指標:
fn main() { let five = Box::new(5); println!("five: {}", *five); }
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:?}"); }
This slide should take about 8 minutes.
-
Box
is likestd::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 aList
directly into theList
, the compiler would not be able to compute a fixed size for the struct in memory (theList
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, aBox
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
。這樣一來,編譯器可以將記憶體配置最佳化: