Menu
Coddy logo textTech

動的メモリ (new/delete)

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 14/104。

ポインタと参照を理解したところで、これらを動的メモリ割り当てで活用してみましょう。new 演算子と delete 演算子を使用すると、実行時にヒープ上にオブジェクトを作成したり破棄したりできます。

new を使用してメモリを割り当て、そのポインタを取得します:

int* num = new int;        // 単一の整数を割り当てる
*num = 42;                 // ポインタを介して値を代入する

Player* player = new Player("Hero");  // オブジェクトを割り当てる

メモリを解放するために、すべての new には対応する delete が必要です:

delete num;      // 単一のオブジェクトを解放する
delete player;   // デストラクタを呼び出し、その後メモリを解放する

配列の場合は、new[]delete[] を使用します:

int* scores = new int[5];    // 5つの整数の配列を割り当てる
scores[0] = 100;

delete[] scores;             // 配列を解放する - 角括弧に注意してください!

避けるべき一般的な間違い:

// メモリリーク - deleteを忘れた
int* ptr = new int(10);
ptr = new int(20);    // 最初の割り当てへのアクセスを失った!

// ダングリングポインタ - delete後に使用
delete ptr;
*ptr = 5;             // 未定義の動作!

// 不一致なdelete
int* arr = new int[10];
delete arr;           // 間違い!delete[]であるべき

削除した後は、誤った再利用を避けるためにポインタを nullptr に設定してください。手動のメモリ管理はエラーが発生しやすいため、モダンなC++ではスマートポインタが好まれます。これについては次に詳しく見ていきます。

challenge icon

チャレンジ

簡単

newdelete を使用した動的メモリ割り当てを実演する、シンプルなメッセージ保存システムを構築しましょう。

コードを整理するために、2つのファイルを作成します。

  • MessageBox.h: メッセージの配列を動的に管理する MessageBox クラスを定義します。このクラスには以下のものを含める必要があります。
    • 動的に割り当てられた文字列配列へのプライベートポインタ
    • 現在のメッセージ数を追跡するプライベートな整数
    • 最大容量を格納するプライベートな整数
    • 容量を受け取り、new[] を使用して配列を割り当てるコンストラクタ
    • delete[] を使用してメモリを適切に解放し、"MessageBox destroyed" と出力するデストラクタ
    • 空きがある場合にメッセージを追加し、成功した場合は true、満杯の場合は false を返す addMessage(string msg) メソッド
    • 格納されている各メッセージをそれぞれの行に出力する printAll() メソッド
  • main.cpp: 入力から容量の値とメッセージの数を読み取ります。次に、その数だけメッセージ文字列を読み取ります。new を使用してヒープ上に MessageBox を作成し、すべてのメッセージを追加して printAll() を呼び出し、その後 MessageBox を適切に削除してメモリを解放します。

入力形式は以下の通りです:

  • 1行目:容量(整数)
  • 2行目:追加するメッセージの数(整数)
  • 続く行:1行につき1つのメッセージ

注意:すべての new には対応する delete が必要であり、すべての new[] には対応する delete[] が必要です。削除した後は、ポインタを nullptr に設定するのが良い習慣です。

#include "MessageBox.h" を使用して、main.cpp にヘッダーファイルをインクルードしてください。

チートシート

new を使用して、ヒープ上にメモリを動的に割り当て、そのポインタを取得します:

int* num = new int;        // Allocate single integer
*num = 42;                 // Assign value through pointer

Player* player = new Player("Hero");  // Allocate object

すべての new には、メモリを解放するための対応する delete が必要です:

delete num;      // Free single object
delete player;   // Calls destructor, then frees memory

配列の場合は、new[]delete[] を使用します:

int* scores = new int[5];    // Allocate array of 5 integers
scores[0] = 100;

delete[] scores;             // Free array - note the brackets!

避けるべき一般的な間違い:

// Memory leak - forgot to delete
int* ptr = new int(10);
ptr = new int(20);    // Lost access to first allocation!

// Dangling pointer - using after delete
delete ptr;
*ptr = 5;             // Undefined behavior!

// Mismatched delete
int* arr = new int[10];
delete arr;           // Wrong! Should be delete[]

削除した後は、誤った再利用を避けるためにポインタを nullptr に設定してください。

自分で試してみよう

#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;

int main() {
    int capacity;
    int numMessages;
    
    // 容量とメッセージの数を読み取る
    cin >> capacity;
    cin >> numMessages;
    cin.ignore(); // 数値の後の改行をクリアする
    
    // TODO: new を使用してヒープ上に MessageBox を作成する
    
    // TODO: すべてのメッセージを読み取り、MessageBox に追加する
    for (int i = 0; i < numMessages; i++) {
        string message;
        getline(cin, message);
        // メッセージを MessageBox に追加する
    }
    
    // TODO: printAll() を呼び出してすべてのメッセージを表示する
    
    // TODO: メモリを解放するために MessageBox を削除する
    // 削除した後はポインタを nullptr に設定することを忘れないこと
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン