C++には、スマートポインタという配列の進化版みたいな機能があります。
スマートポインタの強みは「メモリ管理」です。
本来、配列を使う場合は宣言時にメモリ確保するか動的にメモリを確保する必要がありました。
配列の使用時、特に動的にメモリを配置する際にmallocやnewでメモリを確保した後は、必ずdeleteやfreeでメモリを開放しないといけませんでした。
もしfreeを忘れるとメモリリークと呼ばれるメモリ圧迫が置き、後続のプログラムの動作が不安定になるという問題が起きます。
メモリの動的確保
まずはスマートポインタを使わない場合のメモリの動的確保についてプログラムを見ていきましょう。
int main(){
int *arr_ptr = nullptr;
arr_ptr = new int[10];
//上記はまとめて書くこともできる
//int *arr_ptr = new int[10];
・・・・
delete arr_ptr;
}
このような動的なメモリ確保を用いると、下記のような問題が発生することがあります。
- deleteし忘れてメモリリークが発生する
- newしてないのにdeleteすると、エラーが発生する
これらはメモリ状況の影響を受けるため、たまに落ちるという最も検出の難しいバグの発生に繋がります。
また、配列に関するバグは得てして見つかりにくいものです。謎のデータが表示されて、それが配列が原因だったという経験のある方は多いでしょう。
プログラマの仕事の9割はバグ取りと言われているくらいにはバグ取りは大変であり、バグができにくい仕組みを作ることには非常に価値があります。
スマートポインタ
スマートポインタはこのようなミスを減らすのに役立つ機能を持っています。
スマートポインタは自動でメモリ管理を行ってくれるので、上記の動的メモリ管理の手間が省ける上に、ヒューマンエラーも減らすことが出来ます。
スマートポインタはスコープを抜けると自動的にメモリが開放されるという機能を備えています。
#include <memory>
using namespace std;
int main(){
unique_ptr<int[]>arr_ptr;
arr_ptr = make_unipue<int[]>(10);
//下記のようにまとめて書ける
//unique_ptr<int[]> arr_ptr(new int[10]);
//deleteは不要
}
このように、スマートポインタを使うことでdeleteは不要となります。
また、スマートポインタを使うためには<memory>をインクルードする必要があるので注意が必要です。
おわりに
今回はスマートポインタについて紹介しました。
スマートポインタを使うことで、メモリ管理の手間が省けます。これにより、ユーザーのミスによるバグを防ぐことが出来ます。
スマートポインタにも種類がありますが、違いを理解するのはけっこう大変なので、まずは使ってみて不便さを感じたら他の選択肢も考えると良いでしょう。