@kfurumiya
GitHub
本名
古川 亘
ハンドルネーム
古都こと
しゅみ
ゲーム
プログラミング
好きな言語
TypeScript
Rust
React / React Native
Next.js
AWS / GCP
ウェブパフォーマンス
1991年生まれ
近況
原神(PC版)に
ハマっている
今日のお話
Rustの所有権システム
完全に理解した
本日の献立
Rust is 何
Rustとは
use std::process::exit;
use std::env;
fn main() {
let cli_args: Vec<String> = env::args().collect();
let name = match cli_args.get(1) {
Some(a) => a,
None => exit(0)
};
println!("Hello, {}!", name);
}
Rustとは
Rustの特徴
全ての値に対する
「所有権」が存在する
Rustの特徴
😗
値の所有権
所有権
(ownership)
値の所有権(ownership)
fn main() {
let val = String::from("Hello");
let val2 = val;
println!("{} {}", val, val2);
}
error[E0382]: borrow of moved value: `val`
--> src/main.rs:5:23
|
2 | let val = String::from("Hello");
| --- move occurs because `val` has type `String`, which does not implement the `Copy` trait
3 | let val2 = val;
| --- value moved here
4 |
5 | println!("{} {}", val, val2);
| ^^^ value borrowed here after move
↓コンパイルエラー
値の所有権(ownership)
fn main() {
// ここで値がvalに束縛される
let val = String::from("Hello");
// val2に所有権がムーブし、valは所有権を失う
let val2 = val;
// valは既に所有権を失っているので
// ここでアクセスするとエラー
println!("{} {}", val, val2);
}
Why???
What's?
所有権とムーブセマンティクス
所有権とムーブセマンティクス
所有権とムーブセマンティクス
fn main() {
let val = String::from("Hello");
{
let _list = vec![val]; // valがVectorにmoveする
} // ここで_listもvalもfreeされてしまう
println!("{}", val); // もう戻ってこない
}
所有者のスコープを抜けると
freeされてしまう
借用
(borrowing)
ムーブの問題
fn string_len(text: String) -> usize {
// returnしているのがusizeなので
// 受け取ったString自体は元の場所にムーブしない……
text.len()
}
fn main() {
let val = String::from("Hello");
// ムーブしたStringが戻ってこない
let len = string_len(val);
// エラー!元のStringはfreeされてしまった……
println!("{} {}", val, len);
}
借用(borrowing)
借用してみる
fn string_len(text: &String) -> usize {
// Stringを借用しているだけなので
// 返す必要はない
text.len()
}
fn main() {
let val = String::from("Hello");
// Stringは貸してるだけ
// 所有権はvalの元にある
let len = string_len(&val);
// 動く!!!!
println!("{} {}", val, len);
}
可変参照の借用
fn string_len(text: &String) -> usize {
// エラー!借用しているだけなので
// mutateできない…
text.push_str(" World!");
text.len()
}
fn string_len_2(text: &mut String) -> usize {
// &mut で明示的に可変な借用をする
text.push_str(" World!");
text.len()
}
fn main() {
// 可変な値として束縛する
let mut val = String::from("Hello");
let len = string_len(&val); // エラー!
let len2 = string_len_2(&mut val); // 可変参照を生成する
println!("{} {}", val, len2);
}
ぶら下がりポインタ
fn dangle() -> &String {
let s = String::from("Hello");
return &s;
} // sはここでfreeされる
// よって&sは危険!エラー!
fn main() {
let val = dangle();
}
ライフタイム
(lifetime)
借用のライフタイム
fn main() {
let val = String::from("Hello");
// xのライフタイム 'a
let x = &val;
{
let y = &val; // yのライフタイム 'b
} // 'b ここまで
}// 'a ここまで
'a 'b 'c…と自動的に振られていく!
スコープに名前付けてるイメージ
ライフタイムが確定しない場合
// エラー
// xのライフタイム'aとyのライフタイム'bが自動的に振られるが
// どちらが返るかわからない → 戻り値のライフタイムも確定しない
fn longer(x: &String, y: &String) -> &String {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let a = String::from("aa");
let b = String::from("aaa");
let result = longer(&a, &b);
println!("{}", result)
}
ライフタイムを明示してあげる
// ライフタイムを明示する
fn longer<'a>(x: &'a String, y: &'a String) -> &'a String {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let a = String::from("aa");
let b = String::from("aaa");
let result = longer(&a, &b);
println!("{}", result)
}
まとめ!!
💯 Rustの所有権システム完全に理解した 💯