C++メモリ管理の極意:newとdeleteのエキスパート活用法
C++メモリ管理の極意:newとdeleteのエキスパート活用法
このガイドでは、C++でヒープメモリを確保・解放するnewとdeleteの使い方を、明確で実践的な例で解説します。
C++は実行時にメモリを確保する動的メモリ確保の機能を開発者に提供します。JavaやPythonなどの管理型言語とは異なり、C++はヒープメモリを自動的に回収しません。プログラマーが明示的に解放する必要があります。
newとdelete演算子を使うことでこの基本的なタスクが可能です。これらの演算子はC++における手動メモリ管理の基盤であり、C++標準ライブラリで定義されています。
new演算子
new演算子はヒープ上にメモリブロックを確保し、その最初のバイトへのポインタを返します。例えば:
// intポインタを宣言
int* pointVar;
// newで動的にメモリ確保
pointVar = new int;
// 確保したメモリに値を代入
*pointVar = 45;
このスニペットでは、pointVarは新しく確保されたintのアドレスを受け取ります。newはポインタを返すため、変数はポインタ型でなければなりません。配列の場合、newは最初の要素へのポインタを返します:
int* arr = new int[10]; // arrは10個のintの配列の最初の要素を指す
一般的な構文は:
ポインタ変数 = new データ型; // 単一オブジェクト
ポインタ変数 = new データ型[サイズ]; // 配列
delete演算子
newで確保したオブジェクトや配列が不要になったら、deleteを呼んでメモリをOSに返却すべきです。これを怠るとメモリリークが発生し、パフォーマンス低下やクラッシュの原因になります。
単一オブジェクトの場合:
delete ポインタ変数;
new[]で確保した配列の場合、配列形式を使います:
delete[] ポインタ変数;
完全なライフサイクルの例:
// intを確保
int* pointVar = new int;
*pointVar = 45;
cout << *pointVar; // 出力: 45
// 解放
delete pointVar;
ヒント: すべてのnewには対応するdelete(配列ならdelete[])をペアにしてください。本番コードではRAIIやスマートポインタ(std::unique_ptrなど)を使って自動化しましょう。
例1: 基本的な動的確保
#include <iostream>
using namespace std;
int main() {
int* pointInt;
float* pointFloat;
pointInt = new int;
pointFloat = new float;
*pointInt = 45;
*pointFloat = 45.45f;
cout << *pointInt << endl;
cout << *pointFloat << endl;
delete pointInt;
delete pointFloat;
return 0;
}
出力
45 45.45
このプログラムは2つのプリミティブ型の確保、代入、出力、クリーンな解放を示しています。
注意: 動的確保は、サイズが実行時に決まる場合に特に柔軟性を高めます。
例2: float配列の確保
#include <iostream>
using namespace std;
int main() {
int num;
cout << "学生の総数を入力: ";
cin >> num;
float* ptr = new float[num];
cout << "学生のGPAを入力。" << endl;
for (int i = 0; i < num; ++i) {
cout << "学生" << i + 1 << ": ";
cin >> *(ptr + i);
}
cout << "\n学生のGPAを表示。" << endl;
for (int i = 0; i < num; ++i) {
cout << "学生" << i + 1 << " :" << *(ptr + i) << endl;
}
delete[] ptr;
return 0;
}
出力
学生の総数を入力: 4 学生のGPAを入力。 学生1: 3.6 学生2: 3.1 学生3: 3.9 学生4: 2.9 学生のGPAを表示。 学生1 :3.6 学生2 :3.1 学生3 :3.9 学生4 :2.9
プログラムは学生数をユーザーから取得し、それに応じてfloat配列を確保し、入力を受け取り、データを表示し、最後にdelete[]でメモリを解放します。
例3: オブジェクトの動的確保
#include <iostream>
using namespace std;
class Student {
int age;
public:
Student() : age(12) {}
void getAge() {
cout << "Age = " << age << endl;
}
};
int main() {
Student* ptr = new Student();
ptr->getAge();
delete ptr;
return 0;
}
出力
Age = 12
この例ではStudentオブジェクトをヒープ上に作成します。コンストラクタでageを12に初期化し、getAgeメソッドで出力します。使用後、deleteでオブジェクトのメモリを解放します。
モダンC++でのベストプラクティス
- スマートポインタを優先 -
std::unique_ptr、std::shared_ptrで自動管理 - RAIIパターン - リソース確保は初期化時に、解放はデストラクタで
- 生のnew/deleteは最小限に - 低レベルライブラリ実装時などに限定
- 配列にはstd::vector - 動的配列管理のデファクトスタンダード
C言語
- GEデジタル、予知資産管理ソフト発表:保全を事後からプロアクティブへ転換
- Raspberry Pi 3 B+ – アップデートされた機能、仕様、購入ガイド
- Wittmann Battenfeld、新XシリーズとPrimus 14ロボットを発表
- デジタルメモリの基礎:アドレッシング、アクセス、揮発性
- C++構造体とクラス:組み込み開発者のための実践ガイド
- C++変数・リテラル・定数完全ガイド:基礎から実践まで
- C++クラスとオブジェクト完全ガイド:オブジェクト指向プログラミングの実践
- C++ public/protected/private継承の違いを徹底解説
- C++フレンド関数とフレンドクラス:アクセス制御のマスター
- C言語動的メモリ管理:calloc、malloc、freeの解説
- Pythonディレクトリ・ファイル操作マスター:作成、移動、一覧、リネーム、削除