値型・参照型
- 値型:
- 値型(例えば
int
や float
など)はスタックに保存されます。スタックに直接データが格納され、スコープを抜けると自動的に解放されます。
- 参照型:
- 参照型(例えばクラスや配列)はヒープにデータが格納され、その参照(アドレス)だけがスタックに保存されます。ヒープ上のオブジェクトは、ガベージコレクションが不要と判断したときに解放されます。
- 値型 → スタックに直接保存。
- 参照型 → ヒープにデータが保存、スタックにその参照が保存。
スタック・ヒープ
スタック(Stack) と ヒープ(Heap) は、プログラムがメモリを管理する際に使用される領域の2つの異なる方法です。
それぞれの特徴と役割を解説します。
1. スタック(Stack)
スタックは、 LIFO(Last In, First Out) 方式でメモリを管理する領域です。主に関数のローカル変数や、メソッド呼び出し時の情報(戻り先アドレスやパラメータなど)を保存します。
特徴:
- 高速アクセス: スタックはメモリの領域を一括で管理するため、変数の割り当てや解放が非常に高速です。
- 自動管理: 変数はスコープを抜けると自動的に解放されるため、メモリ管理がシンプルです。開発者が手動で解放する必要はありません。
- サイズ制限: スタックは一般的にサイズが小さい(数MB程度)ため、大きなデータ(例: 巨大な配列やオブジェクト)はスタックに格納できません。
使用例:
- 関数のローカル変数(
int
、float
などのプリミティブ型)
- 関数の引数
- 戻りアドレス(呼び出し元に戻るための情報)
イメージ:
関数が呼び出されるごとに、その関数で使用される変数や情報がスタックに積み上げられ、
関数が終了するとそれらが一気に取り除かれる(解放される)。
2. ヒープ(Heap)
ヒープ は、動的にメモリを確保するための領域です。必要に応じてプログラムの実行中に自由にメモリを確保(動的割り当て)し、使い終わったら明示的に解放する必要があります。
特徴:
- 動的メモリ管理: ヒープは必要な分だけ動的にメモリを割り当てることができ、使用が終わったら解放する必要があります(手動解放やガベージコレクションが担当)。
- 大きなメモリ領域: スタックに比べてヒープのサイズは大きく、巨大なデータ構造(例: 大きな配列やオブジェクト)を扱うのに適しています。
- メモリの断片化が発生しやすい: メモリがランダムに割り当てられるため、断片化が起き、アクセス速度が遅くなることがあります。
使用例:
- オブジェクトや配列の動的なメモリ割り当て
- クラスのインスタンス
- ランタイム中にサイズが決まるデータ構造
イメージ:
ヒープに割り当てたメモリは、プログラムがその領域を指すポインタを保持し、
明示的にメモリを解放するまでそのまま残る。
スタックとヒープの違い
- 割り当て方式: スタックはLIFO(順序通りの自動解放)、ヒープは動的に割り当て・解放。
- 管理方法: スタックは自動管理、ヒープは手動またはガベージコレクションで管理。
- 速度: スタックはヒープよりも高速にアクセス可能。
- サイズ: スタックは一般にサイズが小さく、ヒープはより大きなメモリ領域を持つ。
まとめ
- スタック: 高速で自動管理されるメモリ領域、小さなデータに適している。
- ヒープ: 大きなデータや動的なメモリ割り当てが必要な場合に利用されるが、手動解放やガベージコレクションが必要。