所有権 備忘録

所有権

  • 移譲 (Move)
  • 借用 (Borrow)

移譲

let a = String::from("Hello World");
let b = a; // 値の所有権が移ると変数aは二度と使えない

借用

参照にすることで、値の借用となる。

let a = String::from("Hello World");
let b = &a; // immutable borrowが発生

借用ルール

mutable borrowが発生中は、他からの借用はできない。

let mut a = String::from("Hello");
let b = &mut a; // muttable borrowが発生
let c = &a;     // immutable borrowが発生 NG
println!("{}", b);

immutable borrowが発生中は、mutable borrow はNG

let mut a = String::from("Hello");
let b = &a[..]; // &str  imutable borrow
a.clear(); // mutable borrowが発生 NG
println!("{}", b);

ライフタイム

参照はライフタイムを持つ。 ライフタイムは基本自動付与されるが、関数の返り値で参照を返す場合は、明示する必要がある。

'static ライフタイム変数はプログラミ開始から終了まで値が生存していることを示すことが出来る特別な値

// プログラム開始から最後まで生存することを保証する
fn hello() ->&'static str {
    "hello"
}

以下のように ジェネリックス ライフタイム パラメーター として引数と同じライフタイムを持つことを宣言することが可能

// 引数と同じライフタイムであることを保証する
fn longest<'a>(lhs: &'a String, rhs: &'a String) -> &'a String {
    if lhs.len() > rhs.len() {
        lhs
    } else {
        rhs
    }
}

参照をフィールドとして持つstructはライフタイムパラメーターを付ける必要がある。

// 参照をフィールドとして保つ場合は、ライフタイムパラメーターをつける
struct Bar<'a> {
    foo: &'a Foo,
}

impl<'a>  Bar<'a> {
    fn new(the_foo: &Foo) -> Bar {
        Bar { foo: the_foo }
    }
    fn get_foo(&'a self) -> &'a Foo {
        self.foo
    }
}

fn main() {
    let _myfoo = Foo{};
    let _mybar = Bar::new(&_myfoo);
    let _foo = _mybar.get_foo();
}