スマートポインタの基本
標準ライブラリの高機能なスマートポインタの話ではなく、スマートポインタのひな型の説明
本記事の前提条件は以下の通りです。
- 初心者向け
- とは言っても、何らかのプログラムはそれなりに書けるけど、C とか C++ はちょっと、という人向け
- ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
- Visual Studio 2013 くらい~
- Windowsプログラム (CUI, GUI)
- コードの検証
- 開発環境: Visual Studio 2022, x64, Release ビルド
- 実行環境: Windows 10
- 本記事は上から順番に読む前提となっている
- 「Visual Studio 2013 くらい~」と書いてあるが、本記事の内容だと現在過去未来のどのバージョンでもほぼ同じ
- 「Windowsプログラム (CUI, GUI)」と書いてあるが、本記事の内容だとどの OS でもほぼ同じ
スマートポインタでない場合
100バイトのメモリをヒープに確保して利用することを考える。
スマートポインタを使わない場合は以下のようになる。
// c
char* p = (char*)malloc(100);
strcpy_s(p, 100, "hello");
printf("%s\n", p);
free(P);
// c++
auto* p = new char[100];
strcpy_s(p, 100, "hello");
std::cout << p << "\n";
delete [] p;
メモリの確保と解放が別になっているので、解放し忘れ、いわゆるメモリリークを起こしやすい。
また、確保したメモリを別のオブジェクトに渡して使うような場合、解放のタイミングが非常に難しいものとなる。
RAII に基いてクラス化する
次のようなクラスを考える。
class Buffer
{
public:
Buffer(size_t size)
{
p = new char[size];
}
~Buffer()
{
delete [] p;
}
char* p = nullptr;
};
次のように使える。
Buffer buf(100);
strcpy_s(buf.p, 100, "hello");
std::cout << p << "\n";
スコープから外れるときにデストラクタが呼ばれるため、メモリは適切に解放される。
これをスマートポインタというのもおこがましいが、これがスマートポインタの基本となる。
上記の例だと、メモリの解放は自動的に行われるようになったが、他の関数に渡したり、複数のオブジェクト間で共有したりといったことはうまくできない。
標準ライブラリにある、std::unique_ptr
, std::shared_ptr
などはもっと便利な機能が備わっており、非常に柔軟に使うことができる。
以上。