10.1 スタックとヒープ
単純化すると、メモリは次のように分類できます。
スタック
関数呼び出し
ローカル変数
比較的小さく寿命が明確な値
高速で自動的に解放されます。
ヒープ
実行時に大きさが決まるデータ
寿命が関数呼び出しを超えるデータ
オブジェクトや動的配列
解放方法は言語によって異なります。
10.2 ガベージコレクション
不要になったオブジェクトを実行環境が検出し、解放します。
代表例:
Java
C#
Go
JavaScript
Python
PHP
Ruby
開発者が明示的にメモリを解放する必要は基本的にありません。
ただし、次のコストがあります。
実行時オーバーヘッド
停止時間の可能性
メモリ解放タイミングが完全には予測できない
10.3 所有権
Rustでは、ガベージコレクタの代わりに所有権でメモリを管理します。
基本原則は次です。
値には所有者がいる
所有者がスコープを抜けると値が解放される
同時に安全な参照規則を守る
{
let name = String::from("Taro");
}
// ここで自動解放
所有権が移動する場合があります。
let a = String::from("hello");
let b = a;
// aは以後使用不可
これは二重解放や解放後参照をコンパイル時に防ぐ仕組みです。
10.4 借用
所有権を移さず、一時的に値を参照します。
fn length(value: &String) -> usize {
value.len()
}
可変参照にはより厳しい規則があります。
fn append(value: &mut String) {
value.push_str("!");
}
Rustの所有権・借用は特殊に見えますが、解決している問題は他言語と共通です。
誰が値を管理するのか
誰が変更できるのか
いつ解放できるのか
同時アクセスは安全か