Rust-ownership
錆-所有権
プログラムのメモリは、次のように割り当てることができます-
- スタック
- Heap
スタック
スタックは、後入れ先出し順に従います。 スタックには、コンパイル時にサイズがわかっているデータ値が格納されます。 たとえば、固定サイズi32の変数は、スタック割り当ての候補です。 そのサイズはコンパイル時に既知です。 サイズが固定されているため、すべてのスカラー型をスタックに格納できます。
実行時に値が割り当てられる文字列の例を考えてみましょう。 このような文字列の正確なサイズは、コンパイル時に決定できません。 したがって、スタック割り当ての候補ではなく、ヒープ割り当ての候補です。
Heap
ヒープメモリには、コンパイル時にサイズが不明なデータ値が格納されます。 動的データの保存に使用されます。 簡単に言えば、プログラムのライフサイクルを通じて変化する可能性があるデータ値にヒープメモリが割り当てられます。 ヒープはメモリ内の領域で、スタックと比較すると整理されていません。
所有権とは何ですか?
Rustの各値には、値の*所有者*と呼ばれる変数があります。 Rustに保存されているすべてのデータには、所有者が関連付けられています。 たとえば、構文-_let age = 30では、age_は値_30_の所有者です。
- 各データは、一度に1人の所有者のみを持つことができます。
- 2つの変数が同じメモリ位置を指すことはできません。 変数は常に異なるメモリ位置を指します。
所有権の譲渡
価値の所有権は次の方法で譲渡できます-
- ある変数の値を別の変数に割り当てる。
- 関数に値を渡します。
- 関数から値を返します。
ある変数の値を別の変数に割り当てる
言語としてのRustの主なセールスポイントは、メモリの安全性です。 メモリの安全性は、誰が何をいつ使用できるかを厳密に制御することで実現されます。
次のスニペットを考慮してください-
fn main(){
let v = vec![1,2,3];
//vector v owns the object in heap
//only a single variable owns the heap memory at any given time
let v2 = v;
//here two variables owns heap value,
//two pointers to the same content is not allowed in rust
//Rust is very smart in terms of memory access ,so it detects a race condition
//as two variables point to same heap
println!("{:?}",v);
}
上記の例では、ベクトルvを宣言しています。 所有権の考え方は、1つの変数のみがリソースにバインドされるということです。 v はリソースにバインドするか、 v2 はリソースにバインドします。 上記の例では、エラーがスローされます-移動した値の使用: `v`。 これは、リソースの所有権がv2に転送されるためです。 これは、所有権がvからv2(v2 = v)に移動され、移動後にvが無効になることを意味します。
関数に値を渡す
ヒープ内のオブジェクトをクロージャーまたは関数に渡すと、値の所有権も変わります。
fn main(){
let v = vec![1,2,3]; //vector v owns the object in heap
let v2 = v; //moves ownership to v2
display(v2); //v2 is moved to display and v2 is invalidated
println!("In main {:?}",v2); //v2 is No longer usable here
}
fn display(v:Vec<i32>){
println!("inside display {:?}",v);
}
関数から値を返す
関数の実行が完了すると、関数に渡された所有権は無効になります。 この問題を回避するには、関数が所有オブジェクトを呼び出し元に返すようにします。
fn main(){
let v = vec![1,2,3]; //vector v owns the object in heap
let v2 = v; //moves ownership to v2
let v2_return = display(v2);
println!("In main {:?}",v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> {
//returning same vector
println!("inside display {:?}",v);
}
所有権とプリミティブ型
プリミティブ型の場合、ある変数の内容が別の変数にコピーされます。 したがって、所有権の移動は発生しません。 これは、プリミティブ変数がオブジェクトよりも少ないリソースで済むためです。 次の例を考慮してください-
fn main(){
let u1 = 10;
let u2 = u1; //u1 value copied(not moved) to u2
println!("u1 = {}",u1);
}
出力は– 10です。