メモリの解放を忘れるなど、生ポインタを使うと、メモリリークの可能性が高まります。ポインタを使う場面では、生ポインタよりもスマートポインタの利用が推奨されています。スマートポインタと生ポインタは、C++において動的メモリ管理の手段として使用されるものですが、いくつかの重要な違いがあります。
- 自動メモリ管理:
- 生ポインタ: 手動でメモリの確保と解放が必要であり、開発者がメモリリークや二重解放などの問題に注意する必要があります。
- スマートポインタ: メモリ管理を自動化し、所有権と解放をスマートに扱う。例えば、std::shared_ptrやstd::unique_ptrなどは、対象となるオブジェクトが不要になるときに自動的にメモリを解放する。
- 所有権の管理:
- 生ポインタ: 所有権の管理が明示的でなく、ポインタが指すメモリがどのオブジェクトに属しているかをコードから把握しづらい。
- スマートポインタ: 所有権がクリアになり、どのスマートポインタがそのメモリを所有しているかがわかりやすい。例えば、std::shared_ptrは複数のポインタが同じオブジェクトを共有でき、std::unique_ptrは単一の所有者しか持てない。
- 安全性:
- 生ポインタ: メモリの所有者が不明確だったり、手動でのメモリ解放の可能性があるため、バグの原因となりやすい。
- スマートポインタ: 手動でのメモリ解放が不要で、自動的に安全にメモリ管理が行われるため、プログラムの安全性が向上する。
- 機能の提供:
- 生ポインタ: メモリの確保・解放以外の特別な機能は提供されていない。ただし、柔軟性が高い。
- スマートポインタ: 所有権の転送や共有、カスタムデリータの指定など、さまざまな機能が提供されている。
- アクセス方法:
- 生ポインタ: アロー演算子 (->) やデリファレンス演算子 (*) を用いてメモリにアクセスする。
- スマートポインタ: 同様にアロー演算子やデリファレンス演算子を使用できるが、その他にもメソッド呼び出しや標準ライブラリの機能を使ってポインタにアクセスできる。
C++には標準ライブラリで提供されるいくつかのスマートポインタがあります。以下は主なものです。
- std::unique_ptr
- 単一の所有者を表すスマートポインタです。一度に1つのポインタだけが同じオブジェクトを所有できます。
- 所有権の独占的な転送が可能で、他のstd::unique_ptrやstd::shared_ptrとは互換性がありません。
- 所有権を持っているstd::unique_ptrがスコープを抜けると、対象のオブジェクトは自動的に解放されます。
- std::shared_ptr
- 複数の所有者を持つスマートポインタです。同じオブジェクトを複数のstd::shared_ptrが共有できます。
- 所有権の共有が可能で、他のstd::shared_ptrやstd::unique_ptrとも互換性があります。
- 最後の所有者がスコープを抜けると、対象のオブジェクトは解放されます。
- std::weak_ptr
- std::shared_ptrから生成され、所有権を共有せず、オブジェクトの生存を参照するだけのポインタです。
- サイクル参照を防ぐために使用されることがあります。std::weak_ptrがオブジェクトの生存を確認し、生存していればstd::shared_ptrに変換して利用できます。
それでは、スマートポインタのstd::shared_ptrの基本的な使い方を紹介します。std::shared_ptrは、複数のstd::shared_ptrが同じオブジェクトを共有でき、そのオブジェクトが不要になったときに自動的にメモリを開放します。