Rust勉強メモ/参照
生存期間
ある変数(xとする)の参照を別の変数(rとする)に格納する場合
参照の生存期間はxの生存期間に内包され
rの生存期間を内包しなければならい
ダメな例 「プログラミングRust 第2版」p.97
code:Rust
{
let r;
{
let x = 1;
r = &x;
}
assert_eq!(*r, 1); // bad: reads memory x used to occupy
}
生存期間の明示
「プログラミングRust 第2版」p.100
生存期間'aはコンパイラが自動で補ってくれている?
code:コンパイラが補完する'aを明示的に指定.rs
static mut STASH: &i32 = &128;
fn f<'a>(p: &'a i32) {
unsafe {
STASH = p;
}
}
code:これなら動く.rs
fn f(p: &'static i32) {
unsafe {
STASH = p;
}
}
?コンパイラが補完する生存期間
関数が引数として参照を1つだけ取り、1つだけ参照を返す場合には、Rustコンパイラはこれらの参照が同じ生存期間を持つと仮定する。
「プログラミングRust 第2版」p.103
この仮定ではダメな関数の例はこんな感じ?
code:Rust
static mut FOO: i32 = 0_i32;
static mut REFER: &i32 = &1;
//fn ret_static_ref<'a>(p: &'a i32) -> &'static i32 { fn ret_static_ref(p: &i32) -> &i32 { unsafe {
&FOO
}
}
fn test_ret_static_ref() {
assert_eq!(8, *ret_static_ref(&v));
unsafe {
REFER = ret_static_ref(&v);
assert_eq!(8, *REFER);
}
}
参照を含む構造体
「プログラミングRust 第2版」p.103
code:コンパイル出来ない例.rs
struct S {
r: &i32
}
let s;
{
let x = 10;
s = S { r: &x };
}
assert_eq!(*s.r, 10); // ダメ:ドロップされたxからの読み出し
https://gyazo.com/61c3cda657e5e353eda4199345f56214
参照の生存期間を明示する
「プログラミングRust 第2版」p.104
code:生存期間パラメータを追加した.rs
struct S<'a> {
r: &'a i32
}
'aはSを収めた何かの生存期間を包含していなければならない
rに保持される参照の生存期間は、'aを包含していなければならない
https://gyazo.com/8d58a4dfc7bfbd2f70e14c311e2d8a98
?可変参照とPeekableが難しい
code:コンパイルエラーになってしまう例.rs
enum Num {
One(i32),
Three(i32),
}
fn one<I: Iterator<Item = Num>>(pk: &mut Peekable<I>, i: i32) {
assert_eq!(i, 1);
assert_eq!(pk.next(), Some(Num::One(1)));
}
fn test_peekable() {
let p = &mut v.into_iter().peekable();
if let Some(i) = p.peek() { // &'a mut self -> &'a Num
match i {
Num::One(n) => one(p, *n),
_ => println!("not one"),
}
}
}
https://gyazo.com/216087165c29072a09a79228de6cc85c
なぜ?
今回はi32がCopyを実装しているので&Num::One(n) => one(p, *n),で解決。
selfの生存期間
fn method(self: &Self, x: &X) -> &T {
戻り値の生存期間はselfと同じ生存期間に補完される
?可変参照の再借用
「プログラミングRust 第2版」p.113
code:コンパイルエラーになる例
let mut y = 20;
let m1 = &mut y; エラー: 可変参照は1度しか借用できない
let m2 = &mut y;
code:コンパイルエラーにならない例
let mut v = (136, 139);
let m = &mut v;
let m0 = &mut m.0;
なぜこのような違いが出るのか
これはコンパイルエラー
code:Rust
fn main() {
let mut v = (136, 139);
let m = &mut v;
let ml = &mut m.0;
m.0 = 2;
println!("{:?}", m);
println!("{}", ml);
}
NLL(Non-lexical Lifetime)による生存期間解析