C++では、オブジェクトの生成時にコンストラクタが呼ばれ、破棄されるときにデストラクタが自動的に呼ばれます。
この仕組みは、オブジェクトの「生まれてから消えるまで」の流れを制御するために重要です。
C++では new
を使うとヒープ領域にメモリを確保し、delete
で解放します。
この2つを使うことで、プログラム実行中に「必要なタイミングでオブジェクトを作り、不要になったら消す」ことができます。
// 17_memory_basic.cpp
#include <iostream>
using namespace std;
class Player {
public:
Player() { cout << "プレイヤー生成!" << endl; }
~Player() { cout << "プレイヤー削除!" << endl; }
};
int main() {
Player* p = new Player(); // 動的に生成
cout << "プレイ中..." << endl;
delete p; // 明示的に削除(デストラクタが呼ばれる)
return 0;
}デストラクタは~Player()のように、~クラス名と同名関数として定義します。
deleteが動作するタイミングで自動的に呼び出されるメソッドとなります。
実行結果(例)
プレイヤー生成!
プレイ中...
プレイヤー削除!
👉 new で確保したオブジェクトは delete
で明示的に破棄しないと、メモリが残り続けます。
// 17_new_single.cpp
Player* p = new Player(); // コンストラクタが呼ばれる// 17_new_with_args.cpp
class Enemy { public: Enemy(int hp) {/*...*/} };
Enemy* e = new Enemy(100); // 引数を渡して生成// 17_new_array.cpp
Enemy* es = new Enemy[10]; // デフォルトコンストラクタ必須std::bad_alloc
例外が投げられます。new (nothrow) で
nullptr が返ることもあります。// 17_new_nothrow.cpp
Enemy* e = new (nothrow) Enemy(100);
if (!e) { /* メモリ不足時の処理 */ }// 17_delete_single.cpp
delete p; // デストラクタが呼ばれ、メモリが解放される
p = nullptr; // ぶら下がりポインタ対策(推奨)delete[] を使う)
// 17_delete_array.cpp
delete[] es; // 配列は必ず delete[]
es = nullptr;delete を
二回呼ばない。delete 後に nullptr
を代入しておくと安全。delete nullptr; は安全
nullptr を delete
しても何も起こりません(安全な空操作)。// 17_memory_basic.cpp
#include <iostream>
using namespace std;
class Player {
public:
Player() { cout << "プレイヤー生成!" << endl; }
~Player() { cout << "プレイヤー削除!" << endl; }
};
int main() {
Player* p = new Player(); // 動的に生成
cout << "プレイ中..." << endl;
delete p; // 明示的に削除(デストラクタが呼ばれる)
return 0;
}実行結果(例)
プレイヤー生成!
プレイ中...
プレイヤー削除!
👉 new で確保したオブジェクトは delete
で明示的に破棄しないと、メモリが残り続けます。
ゲームの世界では、次々とキャラクターや弾、エフェクトなどが登場します。
これらをすべて最初からメモリ上に確保しておくのは非効率です。
たとえば、
new
で新しい敵オブジェクトを生成delete で不要になった敵のメモリを解放このように、必要なときだけ作り、不要になったら削除するという仕組みが「動的なメモリ確保」の考え方です。
// 17_game_enemy_spawn.cpp
#include <iostream>
#include <vector>
using namespace std;
class Enemy {
public:
Enemy(int id) { cout << "敵" << id << " 出現!" << endl; }
~Enemy() { cout << "敵 消滅!" << endl; }
};
int main() {
vector<Enemy*> enemies;
// 敵を3体出現させる
for (int i = 0; i < 3; i++) {
enemies.push_back(new Enemy(i + 1));
}
cout << "敵を全て倒した!" << endl;
// 倒した敵を削除
for (Enemy* e : enemies) {
delete e;
}
return 0;
}実行結果(例)
敵1 出現!
敵2 出現!
敵3 出現!
敵を全て倒した!
敵 消滅!
敵 消滅!
敵 消滅!
👉 new と delete
が連動して動作しており、オブジェクトの寿命管理の大切さが実感できる。
newで動的に敵を生成し、倒したらdeleteで解放する流れを体験する。
// 17_console_mini_game.cpp
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
class Enemy {
int id;
int hp;
public:
Enemy(int id_, int hp_) : id(id_), hp(hp_) {
cout << "敵" << id << " 出現!(HP=" << hp << ")";
}
~Enemy() {
cout << "敵" << id << " 消滅!";
}
void show(int idx) const {
cout << idx << ": 敵" << id << " [HP=" << hp << "]";
}
void takeDamage(int d) { hp -= d; }
bool isDead() const { return hp <= 0; }
};
int main() {
vector<Enemy*> enemies;
int nextId = 1;
const int DAMAGE = 15;
cout << "=== Console Mini Game ===";
cout << "各ターンで敵が1体出現。番号を選んで攻撃(" << DAMAGE << "ダメージ)。-1で終了。";
for (int turn = 1; turn <= 8; ++turn) { // 8ターンだけ遊ぶ
// 1) 敵の出現(動的生成)
int hp = 20 + (turn * 5 % 15); // 20〜34くらいのHPで変化
enemies.push_back(new Enemy(nextId++, hp));
// 2) 状態表示
cout << "--- Turn " << turn << " ---";
if (enemies.empty()) cout << "敵はいない";
for (size_t i = 0; i < enemies.size(); ++i) enemies[i]->show((int)i + 1);
// 3) 入力受付
cout << "攻撃する敵の番号を入力(-1で終了、0でスキップ)> ";
int choice;
if (!(cin >> choice)) { // 入力失敗対策
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '');
cout << "入力エラー。スキップします。";
choice = 0;
}
if (choice == -1) break; // 終了
if (choice > 0 && (size_t)choice <= enemies.size()) {
Enemy* target = enemies[choice - 1];
target->takeDamage(DAMAGE);
cout << "→ 敵に" << DAMAGE << "ダメージ!";
if (target->isDead()) {
cout << "撃破!メモリ解放します。";
delete target; // 4) 撃破 → delete
enemies.erase(enemies.begin() + (choice - 1)); // ベクタから除去
}
} else {
cout << "スキップ。";
}
}
// 5) ゲーム終了時の後始末(delete忘れ防止)
for (Enemy* e : enemies) delete e;
enemies.clear();
cout << "おつかれさまでした!";
return 0;
}ポイント
new Enemy(...)
をターンごとに呼ぶ(動的生成)delete 後に
ベクタからも削除(ぶら下がりポインタを残さない)まずはこの生ポインタ版で寿命管理を体験 → その後に
std::unique_ptrなどへ進むと理解が深まります。
new / delete
を使うと、実行中に動的にオブジェクトを生成・削除できる