やっつけな日常(37) Rustに入ればRustに従え、唐突に Box って何よ?

Joseph Halfmoon

Rustのソースを眺めていて、また分からないものを見つけました。唐突に現れた Box<i32> なるもの。大文字(アッパーキャメルケース)で書かれていることをみると型、それもジェネリック型に見えます。Boxって何なの?調べてみたら値を「ボックス化」してくれるんだとか?ますます分からん?

結論から言えば、BoxというのはRustの標準ライブラリで定義されている型のようです。だから、何も宣言せずに「唐突」に使っても怒られないみたいです。

それに「ボックス化」、これは値をヒープ上に割りあてることだと。ボックス化をする型なのでBox、ベタなネージミングです。

いつもお世話になっております『Rust By Example 日本語版』さまの以下のページから1か所引用させていただきます。

Box, スタックとヒープ

ボックスとは正確にはヒープ上におかれたTの値へのスマートポインタです。ボックスがスコープを抜けると、デストラクタが呼ばれて内包するオブジェクトが破棄され、ヒープメモリが解放されます。

例によって分かったような、まだ引っかかるような。

とりあえずサンプルコードを書いてみた

分からなくてもBox使ってみるもんだ、と。こんな感じ。

fn sample_box() -> Box<i32> {
    let temp: i32 = 123;
    Box::new(temp)
}

fn sample2_box(arg: Box<i32>) {
    println!("BOX in SUB: {}",arg);
}

fn sample_i32(arg: i32) {
    println!("i32 in SUB: {}",arg);
}

fn main() {
    let ax = 456;
    println!("i32: {}",ax);
    sample_i32(ax);
    println!("i32: {}",ax);

    let bx = sample_box();
    println!("BOX: {}",bx);
    println!("BOX*: {}",*bx);
    sample2_box(bx);
//    println!("BOX: {}",bx);
}

比較のため、普通にスタックの上に値がおかれる変数 ax をまずおいて、その後Boxしてみています。

最後の方に // でコメントアウトしてあるところがありますが、ここをコメントアウトしないと、以下のようなエラーになります。

box_error

sample2_boxという関数に Boxを渡してしまうと、その「所有権」はmainの手を離れてしまうので末尾の行ではエラーとなると。ちゃんとヒープ上のオブジェクトの挙動をしているようです。

動作確認

末尾行をコメントアウトして実動作を確かめたものが以下に。

box_result

Box使って、ヒープ上にオブジェクトを置くことができるのは分かったけれども、*つけても、つけなくてもBoxの中の値にアクセスできるのは何故?便利なような、Rustの挙動が読み切れてないと恐ろしいような。

やっつけな日常(36) Rustに入ればRustに従え、ジェネリック型の構造体を作ってみる へ戻る

やっつけな日常(38) Rustに入ればRustに従え、強力すぎる?Rustのenum へ進む