C++のnew/deleteとmalloc/freeの違いを完全ガイド!動的メモリ管理の基本
生徒
「先生、C++のメモリ管理を調べていたら、『new』以外に『malloc』という言葉も出てきました。これらは何が違うんですか?」
先生
「それは中級者への第一歩となる素晴らしい疑問ですね!簡単に言うと、『malloc』はC言語時代の古いやり方で、『new』はC++に合わせて進化した新しいやり方なんです。」
生徒
「新しい方が便利な気がしますが、具体的に何がパワーアップしているんですか?」
先生
「安全性と『お片付けの自動化』が大きな違いです。初心者の方にもわかるように、身近な例えを使って詳しく解説していきましょう!」
1. メモリ管理の基本:malloc/freeとnew/delete
プログラミングにおいて、パソコンのメモリを一時的に借りる作業を「動的メモリ確保」と呼びます。C++には、この作業を行うための方法が2種類存在します。
- malloc / free(マロック / フリー): C言語から引き継がれた古い方法です。
- new / delete(ニュー / デリート): C++で導入された、より高機能な新しい方法です。
どちらも「メモリという空き地を借りて、使い終わったら返す」という目的は同じですが、その手続きの丁寧さが全く異なります。パソコンを触ったことがない方でも分かるように例えると、「空き地だけを貸し出すのがmalloc」で、「家具付きの部屋を用意し、入居の手続きまで手伝ってくれるのがnew」という違いがあります。
2. malloc/freeは「サイズ指定」が必要
mallocを使ってメモリを借りる場合、パソコンに対して「何バイト(データの重さの単位)の広さが欲しいか」を正確に伝えなければなりません。これは、未経験者にとっては非常に不便な点です。例えば、整数を入れたいだけなのに「整数は4バイトだから……」と計算する必要があるからです。
対して、newは型(intやdoubleなど)を指定するだけで、パソコンが自動的に最適な広さを計算してくれます。計算間違いによるミスが起きにくいのが、大きなメリットの一つです。
3. 最大の違いは「コンストラクタ」の呼び出し
C++には、データを作成した瞬間に「初期設定」を自動で行うコンストラクタという非常に便利な仕組みがあります。ここが malloc と new の決定的な分かれ道です。
new を使うと、メモリを確保した直後にこの初期設定(コンストラクタ)を自動で実行してくれます。しかし、malloc はただメモリの場所を確保するだけなので、初期設定が行われません。つまり、中身がバラバラの「壊れた状態」のままデータが作られてしまう危険があるのです。
4. 安全性の違い:型チェックの有無
malloc が返すのは「どこの馬の骨かも分からないメモリの住所」です。これを専門用語で void*(ボイドポインタ)と呼びます。これを使うには、自分で「これは整数用の住所ですよ」と無理やり解釈を変える(キャストと呼びます)作業が必要です。
一方、new は最初から「整数用のメモリを確保しました」という情報を持って住所を教えてくれます。これを型安全(かたあんぜん)と呼び、プログラムが予期せぬ動作をしてパソコンが固まったりするのを防いでくれます。
5. C++で推奨されるnew/deleteのコード例
まずは、C++で標準的に使われる new と delete の使い方を見てみましょう。非常にスッキリとした書き方が特徴です。
#include <iostream>
int main() {
// 整数(int)1個分のメモリを確保。自動的に初期設定もされる。
int* myNumber = new int(10);
std::cout << "確保した値は: " << *myNumber << std::endl;
// 使い終わったら delete でお片付け。
delete myNumber;
return 0;
}
確保した値は: 10
このコードでは、new がメモリの計算と確保を同時に行い、さらに「10」という数字で中身を初期化しています。非常に親切な設計ですね。
6. 比較:malloc/freeを使った場合のコード例
次に、同じことを古いやり方である malloc で書いてみます。どれだけ手間が増えるか注目してください。
#include <iostream>
#include <cstdlib> // mallocを使うために必要
int main() {
// 1. サイズを自分で計算し(sizeof)、2. 解釈を無理やり変更して((int*))確保する。
int* oldWay = (int*)malloc(sizeof(int));
if (oldWay != nullptr) {
*oldWay = 20; // 自分で値を入れないと中身はデタラメ
std::cout << "mallocで確保した値: " << *oldWay << std::endl;
// 3. 返却は free を使う。
free(oldWay);
}
return 0;
}
mallocで確保した値: 20
一目瞭然ですが、malloc は非常に呪文が長く、初心者にとっては間違いやすいポイントが満載です。sizeof(サイズオフ)という単語も出てきて、メモリの物理的な大きさを意識しなければなりません。
7. なぜ今でもmallocが存在するのか?
「そんなに不便なら、なぜ malloc なんて残っているの?」と不思議に思うかもしれません。主な理由は以下の通りです。
- 昔のプログラムを直すため: 数十年前に書かれたプログラム(C言語)は
mallocで動いており、それらとの互換性を保つためです。 - システムに近い深い部分: パソコンのOS(WindowsやLinuxなど)の深い場所では、C言語とのやり取りが必要になるため、あえて使われることがあります。
しかし、これから新しくC++を学ぶあなたが、日常的なプログラミングで malloc を選ぶ理由はほとんどありません。
8. 絶対に守るべきルール:混ぜるな危険!
C++のメモリ管理において、最も恐ろしい間違いが「混ぜて使うこと」です。
newで借りたなら、必ずdeleteで返す。mallocで借りたなら、必ずfreeで返す。
もし new で借りたものを free で返そうとすると、お片付けの仕方が違うため、プログラムが突然爆発(クラッシュ)したり、メモリが正しく返却されなかったりします。これは、「ガソリン車に軽油を入れてしまう」ような致命的なミスです。
9. 配列の場合の書き方の違い
複数のデータをまとめて扱う「配列」の場合も、違いがハッキリしています。
// C++流:new[] と delete[] を使う
int* cppArray = new int[5];
delete[] cppArray; // []を忘れないのがルール!
// 古いやり方:malloc と free
int* cArray = (int*)malloc(sizeof(int) * 5);
free(cArray);
new[] の方は、データの個数を書くだけで済みますが、malloc の方は「1個の重さ × 5個分」という掛け算まで自分で行わなければなりません。計算を間違えて少なめに確保してしまうと、他のデータが壊れる原因になります。
10. 初心者が覚えるべき結論
ここまで読んでくださった皆さんに、これだけは覚えておいてほしいポイントをまとめます。
- C++なら
new/deleteを使うのが大正義。 安全で簡単、そしてお片付けまでしっかりしてくれます。 malloc/freeは「昔の言葉」だと割り切る。 知識として知っておくのは良いですが、自分から使う必要はありません。- ペアを間違えない。
newとdeleteは一生離れないペアです。
メモリ管理は、パソコンの「資源(リソース)」を扱う非常に重要な作業です。丁寧な new を使いこなすことで、バグの少ない、安定した素晴らしいプログラムを作ることができるようになりますよ!