質問: Val { value: 32 }; test(x); // しかし残念ながらここでmoveされていて test(x) // コンパイルエラー(value used here after move) } ``` しかしこの場合は引数はmoveされてしまい、二度使う事ができません。 こういう形でrefを使った場合にxがmoveされる理由をご存知の方がいたら教えて頂けませんか。
回答: `let x: Val`のとき`test(x)`とすると、関数の引数は「値渡し」になります。値渡しでは、値が関数の引数の領域へmoveします。 `main`ではスタック領域上に`x`のための領域があります。 ``` mainのスタックフレーム x | Val { value: 32} ``` `test`を呼ぶと、まず`main`の`x`の値が、`test`の引数の領域(`arg0`としました)にmoveします。 ``` testのスタックフレーム v | 初期化されてない状態 arg0 | Val { value: 32} mainのスタックフレーム x | 初期化されてない状態(move済み) ``` そして`v`には`arg0`への参照が置かれます。 ``` testのスタックフレーム v | &arg0 arg0 | Val { value: 32} mainのスタックフレーム x | 初期化されてない状態(move済み) ``` これを擬似的なコードで示すと、以下のようになります。 ``` fn test(arg0: Val) { let ref v = arg0; println!("test: {}", v.value) } ``` このように動作しますので、`x`の値がmoveするわけです。 参考: