C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C/C++】new/deleteとmalloc/freeの違いを徹底解説!メモリ管理の基本

C/C++には、実行時にメモリを動的に確保・解放するための仕組みとして、C++のnew/delete演算子と、C言語由来のmalloc()/free()関数があります。どちらもヒープ領域を扱う点は共通していますが、性質や使い方には重要な違いがあります。本記事では、それぞれの基本的な使い方をサンプルコードとともに紹介し、最後に両者の主な相違点を比較表で整理します。

new / delete(C++)

new演算子は、ヒープ領域へのメモリ割り当てを要求します。十分な空きメモリが存在すれば、確保したメモリを初期化してポインタ変数に結び付け、そのアドレスを返します。

delete演算子は、newで確保したメモリを解放するために使用します。プログラマは、不要になったポインタ変数が指すメモリを、任意のタイミングで解放できます。

以下は、C++におけるnew/delete演算子の使用例です。

サンプルコード

#include <iostream>
using namespace std;

int main () {
    int *ptr1 = NULL;
    ptr1 = new int;
    float *ptr2 = new float(299.121);
    int *ptr3 = new int[28];

    *ptr1 = 28;

    cout << "Value of pointer variable 1 : " << *ptr1 << endl;
    cout << "Value of pointer variable 2 : " << *ptr2 << endl;

    if (!ptr3)
        cout << "Allocation of memory failed\n";
    else {
        for (int i = 10; i < 15; i++)
            ptr3[i] = i+1;

        cout << "Value of store in block of memory: ";
        for (int i = 10; i < 15; i++)
            cout << ptr3[i] << " ";
    }
    delete ptr1;
    delete ptr2;
    delete[] ptr3;

    return 0;
}

実行結果

Value of pointer variable 1 : 28
Value of pointer variable 2 : 299.121
Value of store in block of memory: 11 12 13 14 15

この例では、単一のint型・float型のメモリ確保に加え、配列として28個分のint型メモリを確保しています。配列として確保したメモリを解放する際は、delete[]を使用する点に注意してください。

malloc / free(C言語)

malloc()関数は、指定されたサイズ(バイト数)のメモリを確保し、その先頭バイトへのポインタを返します。確保に失敗した場合はNULLポインタを返します。

free()関数は、malloc()で確保したメモリを解放するために使用します。free()を呼び出してもポインタ変数の値そのものは変化しないため、ポインタは引き続き同じメモリ位置を指し続けます。解放済みのポインタにアクセスしないよう注意しましょう。

以下は、C言語におけるmalloc/freeの使用例です。

サンプルコード

#include <stdio.h>
#include <stdlib.h>
int main() {
    int n = 4, i, *p, s = 0;
    p = (int*) malloc(n * sizeof(int));

    if(p == NULL) {
        printf("\nError! memory not allocated.");
        exit(0);
    }

    printf("\nEnter elements of array : ");

    for(i = 0; i < n; ++i) {
        scanf("%d", p + i);
        s += *(p + i);
    }
    printf("\nSum : %d", s);
    free(p);

    return 0;
}

実行結果

Enter elements of array : 32 23 21 8
Sum : 84

この例では、4個分のint型メモリをmalloc()で確保し、ユーザーの入力値を格納して合計を表示しています。確保が成功したかどうかをNULLチェックで確認してから使用している点もポイントです。

new/delete と malloc/free の主な違い

項目new / deletemalloc / free
種類演算子ライブラリ関数
対応言語C++専用C / C++の両方で使用可能
サイズの指定型から自動的に計算されるsizeofなどを用いてバイト数を明示する必要がある
戻り値の型要求した型のポインタvoid*(キャストが必要な場合がある)
コンストラクタ/デストラクタnew時にコンストラクタ、delete時にデストラクタが呼ばれる呼ばれない(純粋なメモリの確保・解放のみ)
失敗時の挙動std::bad_alloc例外をスローするNULLを返す
再確保直接はサポートされないrealloc()で拡張・縮小が可能

まとめ

C++でオブジェクト指向的なプログラムを書く場合、コンストラクタやデストラクタが適切に呼び出されるnew/deleteを使うのが基本です。一方、C言語との互換性が必要な場面や、realloc()による柔軟な再確保を行いたい場合にはmalloc()/free()が有効です。ただし、同一プログラム内で両者を混在させると、解放忘れや二重解放などの不具合につながりやすいため、原則としてどちらか一方に統一することをおすすめします。

  1. C++におけるドット演算子(.)とアロー演算子(->)の違いを徹底解説

    C++では、ドット演算子(.)とアロー演算子(->)はどちらもクラスのメンバーにアクセスするために使用されますが、それぞれ使用される場面が異なります。C++において、class、struct、unionとして宣言された型はすべて「クラスタイプ」とみなされるため、以下の説明はこれら3つすべてに当てはまります。基本的な使い分けa.b は、b がオブジェクト a(またはオブジェクトへの参照[1])のメンバーである場合にのみ使用できます。つまり、a.b の形式では、a は常にクラスの実際のオブジェクト(またはその参照)でなければなりません。a->b は、本質的に (*a).b の省略記法で

  2. C++における#defineとconstキーワードの違いとは?

    #defineとconstの基本的な違い#defineディレクティブはプリプロセッサディレクティブです。プリプロセッサは、コンパイラがソースコードを認識する前に、マクロをその定義内容で単純に置き換えます。イメージとしては、ソースコード全体に対して自動的に実行される「検索と置換」のようなものです。const変数の特徴一方、constによる変数宣言は、言語仕様上の実際の変数を宣言するものです。そのため、通常の変数と同じように扱うことができます。具体的には、以下のような操作が可能です。アドレスの取得(ポインタや参照への代入)関数への引数としての受け渡しキャストや型変換パフォーマンスとスコープの違いコ