[C++] new deleteの使い方についてわかりやすく解説

C++では、動的メモリ管理を行うためにnewdeleteを使用します。

newは、指定した型のメモリをヒープ領域に確保し、そのメモリのアドレスを返します。

例えば、int* ptr = new int;は整数型のメモリを確保し、そのアドレスをptrに格納します。

一方、deletenewで確保したメモリを解放します。

メモリリークを防ぐため、delete ptr;のように使用し、確保したメモリを適切に解放することが重要です。

配列の場合はdelete[]を使用します。

この記事でわかること
  • newdeleteの基本的な使い方
  • メモリリークの概念とその防止方法
  • 配列の動的メモリ確保の方法
  • カスタムデリータの実装方法
  • スマートポインタの利点と使用方法

目次から探す

newとdeleteの基本

new演算子とは

new演算子は、C++において動的にメモリを確保するための演算子です。

これにより、プログラムの実行中に必要なメモリを確保し、オブジェクトを生成することができます。

newを使用することで、スタックではなくヒープ領域にメモリを割り当てることができ、プログラムの実行が終了するまでそのメモリを保持することが可能です。

以下は、new演算子を使用してオブジェクトを生成する例です。

class Sample {
public:
    Sample() {
        // コンストラクタ
    }
    void display() {
        std::cout << "Sampleクラスのオブジェクトです。" << std::endl;
    }
};
int main() {
    Sample* obj = new Sample(); // new演算子でメモリを確保
    obj->display();
    // メモリの解放は後で行う
}
Sampleクラスのオブジェクトです。

delete演算子とは

delete演算子は、new演算子で確保したメモリを解放するために使用されます。

メモリを解放することで、メモリリークを防ぎ、プログラムの効率を向上させることができます。

deleteを使用する際は、必ず対応するnewで確保したメモリを解放する必要があります。

以下は、delete演算子を使用してメモリを解放する例です。

delete obj; // 確保したメモリを解放

newとdeleteの基本的な使い方

newdeleteの基本的な使い方は以下の通りです。

これらを正しく使用することで、動的メモリ管理を適切に行うことができます。

以下の表に、newdeleteの基本的な使い方をまとめました。

スクロールできます
演算子説明使用例
newメモリを動的に確保するSample* obj = new Sample();
delete確保したメモリを解放するdelete obj;
new[]配列のメモリを動的に確保するint* arr = new int[10];
delete[]配列のメモリを解放するdelete[] arr;

これらの基本を理解することで、C++におけるメモリ管理の基礎を築くことができます。

メモリ管理の重要性

メモリリークとは

メモリリークとは、プログラムが動的に確保したメモリを解放せずに失ってしまう現象を指します。

これにより、使用可能なメモリが徐々に減少し、最終的にはプログラムがクラッシュしたり、システム全体のパフォーマンスが低下したりする原因となります。

特に長時間実行されるプログラムや、メモリを多く使用するアプリケーションでは、メモリリークの影響が顕著に現れます。

以下は、メモリリークの例です。

void memoryLeakExample() {
    int* leak = new int[100]; // メモリを確保
    // leakをdeleteしないため、メモリが解放されない
}

メモリリークの防止方法

メモリリークを防ぐためには、以下の方法を実践することが重要です。

これらの方法を用いることで、メモリ管理を適切に行うことができます。

スクロールできます
方法説明
deleteを忘れないnewで確保したメモリは必ずdeleteで解放する。
スコープを意識する自動変数を使用し、スコープが終了すると自動的に解放されるようにする。
スマートポインタを使用std::unique_ptrstd::shared_ptrを使用して、メモリ管理を自動化する。

スマートポインタとの比較

スマートポインタは、C++11以降に導入されたメモリ管理のためのクラスで、動的に確保したメモリを自動的に解放する機能を持っています。

これにより、メモリリークのリスクを大幅に減少させることができます。

以下に、一般的なスマートポインタの種類とその特徴を示します。

スクロールできます
スマートポインタの種類説明使用例
std::unique_ptr唯一の所有権を持つポインタ。自動的にメモリを解放。std::unique_ptr<Sample> ptr = std::make_unique<Sample>();
std::shared_ptr複数のポインタが同じメモリを共有。参照カウントで管理。std::shared_ptr<Sample> ptr = std::make_shared<Sample>();
std::weak_ptrshared_ptrの所有権を持たないポインタ。循環参照を防ぐ。std::weak_ptr<Sample> weakPtr = ptr;

スマートポインタを使用することで、手動でメモリを管理する必要がなくなり、プログラムの安全性と可読性が向上します。

これにより、メモリリークのリスクを大幅に軽減することができます。

newとdeleteの応用

配列の動的メモリ確保

C++では、new演算子を使用して配列の動的メモリを確保することができます。

配列を動的に確保することで、実行時に必要なサイズの配列を作成することが可能になります。

以下は、配列の動的メモリ確保の例です。

int main() {
    int size = 5;
    int* arr = new int[size]; // 配列の動的メモリ確保
    // 配列に値を代入
    for (int i = 0; i < size; ++i) {
        arr[i] = i * 10;
    }
    // 配列の値を表示
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    delete[] arr; // 配列のメモリを解放
}
0 10 20 30 40

カスタムデリータの使用

カスタムデリータは、std::unique_ptrstd::shared_ptrと組み合わせて使用することで、特定の条件や処理に基づいてメモリを解放することができます。

これにより、リソースの管理をより柔軟に行うことが可能になります。

以下は、カスタムデリータの使用例です。

#include <iostream>
#include <memory>
void customDeleter(int* p) {
    std::cout << "カスタムデリータが呼ばれました。" << std::endl;
    delete p; // メモリを解放
}
int main() {
    std::unique_ptr<int, decltype(&customDeleter)> ptr(new int(42), customDeleter);
    std::cout << "値: " << *ptr << std::endl;
    // ptrがスコープを抜けるとカスタムデリータが呼ばれる
}
値: 42
カスタムデリータが呼ばれました。

クラスとnew/deleteの関係

C++では、クラスのインスタンスを動的に生成する際にnew演算子を使用し、インスタンスが不要になった際にはdelete演算子を使用してメモリを解放します。

クラスのコンストラクタとデストラクタは、newdeleteの使用において重要な役割を果たします。

以下は、クラスとnew/deleteの関係を示す例です。

class MyClass {
public:
    MyClass() {
        std::cout << "MyClassのコンストラクタが呼ばれました。" << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClassのデストラクタが呼ばれました。" << std::endl;
    }
};
int main() {
    MyClass* obj = new MyClass(); // コンストラクタが呼ばれる
    delete obj; // デストラクタが呼ばれる
}
MyClassのコンストラクタが呼ばれました。
MyClassのデストラクタが呼ばれました。

このように、クラスのインスタンスを動的に生成する際には、newdeleteを適切に使用することで、リソースの管理を行うことができます。

よくある質問

newとmallocの違いは何ですか?

newmallocはどちらもメモリを動的に確保するための手段ですが、いくつかの重要な違いがあります。

newはC++の演算子であり、オブジェクトのコンストラクタを呼び出して初期化を行います。

一方、mallocはCの関数で、単に指定したサイズのメモリを確保するだけで、初期化は行いません。

また、newは確保したメモリの型を知っているため、型安全性が高いのに対し、mallocはポインタ型を返すため、キャストが必要です。

さらに、newで確保したメモリはdeleteで解放し、mallocで確保したメモリはfreeで解放します。

deleteを使わないとどうなりますか?

deleteを使わない場合、newで確保したメモリは解放されず、メモリリークが発生します。

これにより、プログラムが実行されるたびにメモリが消費され続け、最終的には使用可能なメモリが不足し、プログラムがクラッシュしたり、システム全体のパフォーマンスが低下したりする可能性があります。

特に長時間実行されるアプリケーションでは、メモリリークの影響が顕著に現れます。

スマートポインタを使うべき理由は何ですか?

スマートポインタは、C++11以降に導入されたメモリ管理のためのクラスで、動的に確保したメモリを自動的に解放する機能を持っています。

これにより、手動でdeleteを呼び出す必要がなくなり、メモリリークのリスクを大幅に減少させることができます。

また、スマートポインタは所有権の管理を行うため、プログラムの可読性と安全性が向上します。

特に、std::unique_ptrstd::shared_ptrを使用することで、リソースの管理が容易になり、バグの発生を防ぐことができます。

まとめ

C++におけるnewdeleteの使い方を理解することで、動的メモリ管理の基礎を築くことができます。

メモリリークを防ぐための方法やスマートポインタの利点を学ぶことで、より安全で効率的なプログラムを書くことが可能になります。

ぜひ、これらの知識を活用して、C++プログラミングのスキルを向上させてください。

  • URLをコピーしました!
目次から探す