-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chapter4 所有権を理解する #8
Comments
4.1 所有権とはこれまでの一般的なプログラミング言語がメモリの管理をする場合以下の2つの方法が用いられてきた。
Rustは上記とは異なる、「所有権」と呼ぶ仕組みを採用することで実装者が安全にメモリを使用することができる。 |
4.1.2 所有権規則
|
4.1.3 変数スコープ一般的な他のプログラミング言語と同じ例 {
let s = "Hello!";
println!("{}", s); // ここはスコープ内なので有効
} // ここでスコープを外れるので s は解放される。
println!("{}", s); // ここはスコープ外なので参照できない |
4.1.5 メモリの確保上記のリテラル値の場合は、コンパイル時に必要なメモリの大きさが分かっているが、実行中でないと値が決まらないようなケースの場合はString型を用いて実行時に動的にヒープメモリの確保を行う。 {
let s = String::from("Hello!");
println!("{}", s); // ここはスコープ内なので有効
} // ここでスコープを外れるので s は解放される。
println!("{}", s); // ここはスコープ外なので参照できない String型は、drop()という関数を持っていて、Rustはスコープを外れるときに必ずこの関数を呼ぶ。 |
4.1.5.1 変数とデータの相互作用法: ムーブ下記のように通常のプリミティブな値の場合は、xが持つ '5'という値は {
let x = 5;
println!("x is: {}!", x);
let y = x;
println!("y is: {}!", y); // 1
println!("x is: {}!", x); // 2
} // ここで x,y 両方とも開放
x is: 5!
y is: 5!
x is: 5! String型を用いた場合、String::fromで確保されたメモリはヒープ上に確保されs1の実態はヒープのメモリを指すポインタのようなものでありそれがスタックに積まれる。 今までのC言語のようなメモリ管理の方法であった場合、この後に {
let s1 = String::from("Hello");
println!("{}!", s1);
} Rustではこの問題を、 s2 に s1 を代入したときに s1が指すヒープ上のメモリの参照を無効ににしてコンパイル時にエラーとすることで解決している。これを {
let s1 = String::from("Hello");
println!("{}!", s1);
let s2 = s1;
println!("{}!", s2);
println!("{}!", s1);
}
error[E0382]: borrow of moved value: `s1`
--> src\main.rs:57:24
|
55 | let s2 = s1;
| -- value moved here
56 | println!("{}!", s2);
57 | println!("{}!", s1);
| ^^ value borrowed here after move``` これにより、ヒープ上のメモリを参照する変数は唯一となり二重メモリ開放が行われないことになる。 |
4.1.5.2 変数とデータの相互作用法: クローンヒープ上のメモリの ディープコピーが必要な場合は, {
let s1 = String::from("Hello");
println!("{}!", s1);
let s2 = s1.clone();
println!("{}!", s2);
println!("{}!", s1);
}
Hello!
Hello!
Hello! |
4.1.6 所有権と関数関数の引数に変数を渡すことは、別の変数に代入することと同じなので、上記で説明してきたcopy,moveの考え方に準じる。 fn main() {
{
let s = String::from("Hello!");
takes_ownership(s);
// 関数の引数に渡すことで所有権が移ってしまう。
// println!("{}", s);
let x = 5;
makes_copy(x);
// copyされるのでここでも使用できる
println!("The Value is x: {}", x);
}
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
}
fn makes_copy(number: i32) {
println!("{}", number);
} |
4.1.7 戻り値とスコープ上記の例で、関数の引数に変数を渡すことで所有権の移動が起きることが分かったが fn main() {
{
let mut s = String::from("Hello!");
s = takes_ownership(s);
println!("{}", s);
}
}
fn takes_ownership(some_string: String) -> String {
// 何かの処理
some_string
} 参照と借用この記述を毎回行うのは大変煩わしい。 fun main() {
let s = String::from("Hello!");
let len = reference_ownership(&s);
println!("{} length is {}", s, len);
}
fn reference_ownership(some_string: &String) -> usize {
println!("referenced {}", some_string);
some_string.len()
} 関数の引数に参照を渡すことを 借用 という。 fun main() {
let s = String::from("Hello!");
borrow_ownership(&s);
}
fn reference_ownership(some_string: &String) {
some_string.push_str(", World!");
} 参照を可変なものとするためには、以下のような記述をします。
fun main() {
let mut s = String::from("Hello!");
borrow_mutable_ownership(&mut s);
println!("{}", s);
}
fn borrow_mutable_ownership(some_string: &mut String) {
some_string.push_str(", World!");
} 可変な参照は、同一スコープ内で同時に使用できないという制限があります |
所有権はRustの特徴的な機能、これがあることでガベージコレクタなしで安全性の担保を行うことができる
The text was updated successfully, but these errors were encountered: