安全性、速度、並行性を兼ね備えた言語と、巷でうわさの「Rust」を覗いてみる(その6:参照と借用)
みなさまごきげんよう。
今回も「The Rust Programming Language」を読みながら、
参照と借用についてみていきたいとおもいます。
これまでの復習
教科書の「Listing 4-5」のコードを復習をかねて見ていきます。
fn main() {
let s1 = String::from("hello");
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len);
}
fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // len() returns the length of a String
(s, length)
}
注目すべきは、main関数側の変数 s1 が、 calculate_length 関数の引数 s にmoveされるので、消費されてしまいます。
なので、関数の戻り値をタプルにして、引数 s とサイズを返してします。
こうすることで、s1 > s > s2 と所有権が移動するので、 s1 を利用したい場合に、同じ内容の s2 を利用できます。
しかし、 s1 を再利用したいために、引数で返すのは面倒です。
そこで参照を利用します。
参照を利用する
実引数を &s1 にすることで s1 の参照を作り、仮引数を &String にすることで、その参照を利用できます。
こうすることで、 s1 の所有権が消費されることなく、参照として関数に渡せるようです。
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()
}
なので、 s がスコープを抜けても、 s が指し示している s1 がドロップされることはありません。
ここで言葉の整理をしておきます。
上記の引用によると、参照を作る行為を借用(borrowing)と呼ぶようです。
借用した値を変更する
参照した値を変更するとどうなるのか試す前に、参照を使わない場合の実装を確認してみます。
fn main() {
let s = String::from("hello");
let ss = change(s);
println!("{}", ss);
}
fn change(mut some_string: String) -> String {
some_string.push_str(", world");
some_string
}
ここまで確認した上で、参照の場合を見ていきます。
fn main() {
let s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
--> src/main.rs:8:5
|
7 | fn change(some_string: &String) {
| ------- help: consider changing this to be a mutable reference: `&mut String`
8 | some_string.push_str(", world");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
For more information about this error, try `rustc --explain E0596`.
変数と同様に参照もデフォルトでは不変になっていると書かれています。
では、次に可変の参照で試してみます。
&mut で s の参照を作り、 change 関数の引数を &mut に変更します。fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
可変の参照は、 &mut で生成し、それを受け取る関数側も、 &mut を付けると可変の参照をやり取りすることができます。
次回は、可変の参照の制約について見ていきたいと思います。
この記事を書いた人
-
2008年にアーティスへ入社。
システムエンジニアとして、SI案件のシステム開発に携わる。
その後、事業開発部の立ち上げから自社サービスの開発、保守をメインに従事。
ドメイン駆動設計(DDD)を中心にドメインを重視しながら、保守可能なソフトウェア開発を探求している。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー