C++において、オブジェクトの生成方法や配列の宣言方法は、単なる記述の好みではなく「メモリの確保場所」と「寿命」を決定する重要な要素です。
1. クラスのインスタンス化:2つの方法
静的生成(スタック領域)
Class obj;
- 確保場所: スタック領域
-
寿命: 宣言したスコープ(
{ }内)を抜けると自動的に破棄される。 -
アクセス:
.演算子(例:obj.method()) - 特徴: 高速でメモリリークの心配がない。C++における最も基本的な書き方。
動的生成(ヒープ領域)
Class* obj = new Class();
- 確保場所: ヒープ領域
-
寿命:
delete obj;を呼び出すまでメモリ上に残り続ける。 -
アクセス:
->演算子(例:obj->method()) - 特徴: 実行時にサイズが決まる場合や、スコープを超えてデータを保持したい場合に利用する。ただし、手動管理が必要。
2. 配列の確保場所
配列も同様に、宣言の仕方によって確保される場所が異なります。
固定長配列(スタック)
int arr[100];
- コンパイル時にサイズが決定している必要がある。
- スタック領域のサイズ制限(通常数MB)に注意が必要。巨大な配列はスタックオーバーフローの原因になる。
動的配列(ヒープ)
int* arr = new int[n];
// 使用後は delete[] arr; が必須
- 実行時に要素数
nを決定できる。 - 広大なヒープ領域を利用するため、大きなデータも扱える。
3. モダンC++における推奨事項:std::vector
生の new や delete による管理はミス(メモリリーク)を誘発しやすいため、現代的なC++では std::vector の使用が推奨されます。
#include <vector>
std::vector<int> vec(n);
-
管理:
vectorオブジェクト自体はスタックに置かれるが、中身のデータ実体は自動的にヒープに確保される。 - 利点: スコープを抜ける際にメモリが自動解放されるため、安全かつ柔軟。
まとめ
| 比較項目 | スタック(Class obj;) | ヒープ(new Class();) |
|---|---|---|
| 管理方法 | 自動(コンパイラ任せ) | 手動(deleteが必要) |
| アクセス速度 | 高速 | スタックに比べると低速 |
| サイズ制限 | 小さい | 大きい |
| 主な用途 | 短寿命なオブジェクト、小規模データ | 長寿命なオブジェクト、大規模データ |
基本的には「スタック」または「std::vector」を使い、ポインタが必要な場合は std::unique_ptr などのスマートポインタを検討するのがC++の定石です。