1.6.1 Rustの目標:安全性
の15ページのサンプルプログラムです。
#[derive(Debug)] enum Cereal { Barely, Millet, Rice, Rye, Spalt, Wheat } fn main() { let mut grains: Vec<Cereal> = vec![]; grains.push(Cereal::Barely); drop(grains); println!("{:?}", grains); }
コンパイルエラーがでます。
「Vecdrop
したときにmoveが起きたと言う説明です。
dropは削除であってmoveではないように思えます。
Drop trait
dropは何者なのでしょうか?
drop(grains)
とあるので、グローバルに存在する関数に見えます。
https://doc.rust-lang.org/reference/special-types-and-traits.html?highlight=Drop#drop にはtraitとあるので、Vec structのメソッドなのかもしれません。
https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-Drop をみるとやはりそのようです。
Executes the destructor for this type.
とあるので、デストラクタの実行。
つまりgrains
変数に代入されているVec<Cereal>
インスタンスを破棄しているようです。
ということはCopy traitが実装されている場合は、Vec<Cereal>
インスタンスを破棄した後も、grains
変数を参照している限りはコピーされたインスタンスが生き残るのでしょうか?
ぶら下がりポインタ
この説明は、コンパイラが「ぶら下がりポインタ」を検出する例です。 「ぶら下がりポインタ」とは何でしょうか? ダングリングポインタとは|dangling pointerの危険性と回避 | MaryCoreによると
有効だったメモリ領域が解放処理などによって無効化されたにもかかわらず、そのメモリ領域を参照し続けているポインタのことを、ダングリングポインタと呼ぶ。
まさに、drop(grains)
したあとに、grains
に参照することのようです。
このサンプルプログラムは「ぶら下がりポインタ」の問題を素直に実装した物のようです。
rustでは「ぶら下がりポインタ」を検出するために、moveとかcopyとかその辺の仕組みを使っているようです。 学習を進めていけば、そのうち理解できるのでしょう。