Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
Box<T>
『Box<T>』はヒープ上に値を確保するスマートポインタで、サイズが不明な型の格納や再帰的なデータ構造の定義、トレイトオブジェクトの保持などに使います。
構文
// ヒープに値を確保します。
let b = Box::new(値);
// 中身へのアクセス(自動的に参照外しされます)
*b
// トレイトオブジェクト(動的ディスパッチ)
let obj: Box<dyn トレイト名> = Box::new(値);
// 再帰的なデータ構造
enum List {
Cons(i32, Box<List>),
Nil,
}
メソッド一覧
| メソッド・操作 | 概要 |
|---|---|
| Box::new(v) | 値vをヒープに確保し、Boxを返します。 |
| *b | Derefにより中身の値にアクセスします。 |
| Box<dyn Trait> | トレイトオブジェクトを保持します。実行時に動的ディスパッチされます。 |
| drop(b) | Boxがスコープを抜けると中身ごと自動的に解放されます。 |
サンプルコード
// トレイト定義
trait Animal {
fn sound(&self) -> &str;
}
struct Dog;
struct Cat;
impl Animal for Dog {
fn sound(&self) -> &str { "woof" }
}
impl Animal for Cat {
fn sound(&self) -> &str { "meow" }
}
// 再帰的なリスト構造(Boxなしではコンパイルエラー)
enum List {
Cons(i32, Box<List>),
Nil,
}
fn main() {
// 基本的な使い方:ヒープに値を確保します。
let b = Box::new(5);
println!("{}", *b); // 5(Derefで参照外し)
// トレイトオブジェクト:異なる型を同じVecに入れられます。
let animals: Vec<Box<dyn Animal>> = vec![
Box::new(Dog),
Box::new(Cat),
];
for a in &animals {
println!("{}", a.sound()); // woof / meow
}
// 再帰リスト:Cons(1, Cons(2, Cons(3, Nil)))
let list = List::Cons(1,
Box::new(List::Cons(2,
Box::new(List::Cons(3,
Box::new(List::Nil))))));
// bはスコープを抜けると自動解放されます。
}
概要
『Box<T>』はスタックではなくヒープに値を置くため、コンパイル時にサイズが決まらない型(再帰型など)も扱えます。また、『Box<dyn Trait>』の形でトレイトオブジェクトを保持すると、異なる型を統一的に扱う動的ディスパッチが実現できます。
Rustの『Deref』トレイトにより、『Box<T>』は多くの場面で自動的に参照外しされ、通常の参照と同様に扱うことができます(Deref強制型変換)。
BoxはCloneを自動実装しないため、中身の型がCloneを実装していてもBoxごとclone()するには『#[derive(Clone)]』や明示的な実装が必要です。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。