Box<T>
Box
は、ヒープ上のデータへの所有ポインタです。
fn main() { let five = Box::new(5); println!("five: {}", *five); }
Box<T>
は Deref<Target = T>
を実装しているため、Box<T>
に対して T のメソッドを直接呼び出すことができます。
Recursive data types or data types with dynamic sizes cannot be stored inline without a pointer indirection. Box
accomplishes that indirection:
#[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
は C++ のstd::unique_ptr
と似ていますが、null ではないことが保証されている点が異なります。 -
Box
は次のような場合に役立ちます。- have a type whose size can't be known at compile time, but the Rust compiler wants to know an exact size.
- 大量のデータの所有権をムーブしたい場合。スタック上の大量のデータがコピーされないようにするには、代わりに
Box
によりヒープ上にデータを格納し、ポインタのみが移動されるようにします。
-
仮に
Box
を使用せずにList
をList
に直接埋め込もうとすると、コンパイラはメモリ内の構造体の固定サイズを計算しようとしません(List
は無限サイズになります)。 -
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. -
Though
Box
looks likestd::unique_ptr
in C++, it cannot be empty/null. This makesBox
one of the types that allow the compiler to optimize storage of some enums (the "niche optimization").