![](https://doc.rust-lang.org/book/second-edition/]
Apache License Version 2.0
Understanding Owenership
4.2 References and Borrowings
ある関数にheap構造の変数を引数として渡すと,その変数をその関数の外でまた利用するには,わざわざ関数の返り値としてその変数を受け取らなければならなかった(前節).referenceという機能によって,そうした手間をかけずにすむ.
&記号によってreferenceを実現する.
src/main.rs
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // 引数に&をつける
println!("The length of '{}' is {}. ", s1, len);
}
fn calculate_length(s: &String) -> usize{ // 引数の型名に&をつける
s.len()
}
shell
Finished dev [unoptimized + debuginfo] target(s) in 0.70 secs
Running `target/debug/ownership`
The length of 'hello' is 5.
referenceではownershipが移動しないので,reference変数がスコープから出てしまっても,もとの変数がスコープの中にある限り,もとの変数とそれが持つポインタの指すメモリは消えない.
Mutable References
referenceとして得た変数を関数の中で変更するには,もとの変数がmutableであり,関数を呼ぶときもmutable,また呼ばれた関数も,その引数がmutableであると明示しなければならない.
src/main.rs
fn main() {
let mut s = String::from("hello"); // 最初の変数宣言時にmutと明示
change(&mut s); // 変化させる関数を呼ぶときもmutと明示
println!("{}", s);
}
fn change(some_string: &mut String){ // 引数がmutと明示
some_string.push_str(", world");
}
shell
Finished dev [unoptimized + debuginfo] target(s) in 0.34 secs
Running `target/debug/ownership`
hello, world
ただし,mutable referenceはある変数について同じスコープ内に同時に1つしか存在できない.これはコンパイル時のdata races(データ競合)を防ぐためである.data raceとは,変数が以下の3つの振る舞いをすることである.
1. 2つ以上のポインタが同時に同じデータにアクセスする.
2. 少なくとも1つのポインタがデータを書き込もうとしている.
3. データへのアクセスをsynchronizeする機構がない.
mutable referenceをたかだか1つにすることでdata raceが起こらなくなる.
{}によって新しいスコープを作り,
- src/main.rs*
fn main() {
let mut s = String::from("hello");
{
let r1 = &mut s; // ただちに破棄される
}
let r2 = &mut s; // すでにr1は破棄されているからdata raceは生じない
}
何もしないが,コンパイルできる.
mutableなreferenceがあるなら,その変数へのreferenceはimmutable含め唯一つ.
一方で,mutableでないreferenceならいくつあっても良い.
src/main.rs
fn main() {
let mut s = String::from("hello");
let r1 = &s; // immutable
let r2 = &s; // immutable
let r3 = &s; // mutable
// let r = mut &s // ERROR!
}
何もしないが,コンパイルできる.7行目のコメントを外すとコンパイルエラー
0 件のコメント:
コメントを投稿