Rustの「借用」と「参照」の仕組み、利用方法を理解する:基本からしっかり学ぶRust入門(6)
Rustについて基本からしっかり学んでいく本連載。第6回は、Rustの「借用」と「参照」について。
Rustによるメモリ安全なプログラミングを実現する機能の代表が所有権と借用です。前回は所有権を取り上げました。今回は、所有権による制約の中で値を利用するための借用と参照の仕組みを解説します。
借用とは?
借用(borrowing)とは、所有権を持たずに値を利用することです。所有していないために本来は使えませんが、借りることで使えるようにするものです。実は、この借用は今までも意識しないで利用していました。以下のコードは文字列を出力するコードです。なお、今回のサンプルはborrowsパッケージに作っていきます。
let s = String::from("Hello, Rust!!"); println!("{}", s); // sの1回目の借用 println!("{}", s); // sの2回目の借用
println!()にString型変数のsを渡しているため、1回目の呼び出しで所有権の移動が発生し、2回目の呼び出しではエラーになると思うかもしれません。しかし実行してみるとエラーにはなりません。これは所有権の移動ではなく借用で済ませているからです。つまり借用とは、所有権を失わずに誰かに値を使わせてあげることとも言い換えることができます。この借用のおかげで、所有権の制約の中での値の柔軟な利用が可能になるのです。
借用がない場合
本連載第5回で示したように、所有権の移動に配慮した代入や関数呼び出しが必要になります。借用がない場合、ちょっとした目的の関数を作りたくても冗長な記述を強いられます。1つありがちな例を挙げます。以下のコードは文字列から文字を探して、見つかればその位置を返すという関数です。
fn main() { let s1 = String::from("Hello, world!!"); let c = 'w'; let (s2, pos) = search_position(s1, c); println!("文字'{}'の「{}」中の位置は{}文字目です。", c, s2, pos); // 「文字'w'の「Hello, world!!」中の位置は7文字目です。」 } // sからcを探してその位置を返す関数 fn search_position(s: String, c: char) -> (String, usize) { let pos = s.find(c).unwrap(); (s, pos) }
search_position()関数は、String型変数と文字型変数を受け取って、そのString型変数と位置(整数型)からなるタプルを返します。必要なのは位置だけなのに受け取った変数と戻り値を返している理由は、受け取った文字列を返してあげないと、呼び出し側ではそれを引き続き使えないためです。動きとしては理屈にかなっていますが、位置を調べるのにいちいち元の文字列を渡すのも冗長です。そこで関数を呼び出すとき、所有権を移動させるのではなく借用で済ませられれば、もっとシンプルな形にできそうです。ここで登場するのが参照を使った借用です。
参照とは?
参照とは、所有権を持たずに値の使用を可能にするデータ型の一つです。C/C++におけるポインタに近いと考えれば理解が早いかもしれません。前回は以下のように文字列リテラルを使う場合には変数s1は&strという参照になるということに触れました。
Copyright © ITmedia, Inc. All Rights Reserved.