はじめに
過去に少しだけRustの学習をしていました。今回改めてRustの学習を始めるにあたり、Rustの所有権について学習をしていきます。
所有権とは
Rustの所有権とは、メモリの安全性を保証するための概念です。Rustの所有権には以下の3つのルールがあります。
- 各値は、その値の所有者という変数を持っています。
- 一度に一つの変数のみが値の所有者であることができます。
- 所有者がスコープから外れると、値は破棄されます。
なるほど、日本語としては理解しましたが、実際にコードを書いてみないと理解できない部分もあると思います。そこでコードを書いていきます。
所有権の移動
- 一度に一つの変数のみが値の所有者であることができます。
の部分について確認をしていきます。下記は変数s1をs2に代入したコードです。
fn main() {
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1); // これはエラーになる
}
ビルドすると下記の通りエラーが出ました。これは文字列Helloという値の所有権がs1→s2となったためエラーとなるようです。
error[E0382]: borrow of moved value: `s1`
--> src/main.rs:5:28
|
2 | let s1 = String::from("hello");
| -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
3 | let s2 = s1;
| -- value moved here
4 |
5 | println!("{}, world!", s1); // これはエラーになる
| ^^ value borrowed here after move
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
|
3 | let s2 = s1.clone();
| ++++++++
For more information about this error, try `rustc --explain E0382`.
warning: `Ownership` (bin "Ownership") generated 1 warning
error: could not compile `Ownership` (bin "Ownership") due to previous error; 1 warning emitted
所有権のクローン
それでは所有権を失くすことなく、他の変数へ代入をするのはどうすればいいのか。そこで使用するのが「所有権のクローン」です。
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
ビルド・実行をすると期待通りの結果が得られました。
warning: crate `Ownership` should have a snake case name
|
= help: convert the identifier to snake case: `ownership`
= note: `#[warn(non_snake_case)]` on by default
warning: `Ownership` (bin "Ownership") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 4.03s
Running `target/debug/Ownership`
s1 = hello, s2 = hello
所有権の破棄
- 所有者がスコープから外れると、値は破棄されます。
次に上記のルールについて確認をしていきます。
下記のコードを実行すると、変数s1のスコープが外れたため、s1の値は破棄されることになります。
fn main() {
{
let s = String::from("hello"); // sが"hello"を所有
println!("{}", s); // sは使用可能
} // sのスコープの終わり。sはここで破棄される。
println!("{}", s); // sはすでに破棄されているため、使用不可能
}
実際に下記の通りエラーが出ました。
error[E0425]: cannot find value `s` in this scope
--> src/main.rs:7:20
|
7 | println!("{}", s); // sはすでに破棄されているため、使用不可能
| ^ not found in this scope
For more information about this error, try `rustc --explain E0425`.
error: could not compile `Ownership` (bin "Ownership") due to previous error
最後に
今回はRustの所有権について学習を行いました。次回は参照について学習を行う予定です。