【C++学習|実務向け】C++実務の現場で差がつく!std::shared_ptrのカスタムデリータ活用術

1. 導入:なぜカスタムデリータが必要なのか?

C++のスマートポインタであるstd::shared_ptrは、メモリ管理を自動化し、メモリリークを劇的に減らしてくれます。しかし、実務では「単にdeleteするだけでは不十分なリソース」を扱うケースが多々あります。例えば、C言語のライブラリで確保したメモリの解放(free)や、ファイルハンドルのクローズ、あるいは特定のAPI経由でのリソース破棄などです。これらを適切に管理するために「カスタムデリータ」の知識は不可欠です。

2. 基礎知識:スマートポインタとカスタムデリータの仕組み

std::shared_ptrは、ポインタが指すオブジェクトが不要になった際、デフォルトではdelete演算子を呼び出します。カスタムデリータとは、この「破棄のタイミングで実行される処理」をユーザーが自由に定義できる機能です。

std::unique_ptrとの最大の違いは、型の一部にならないという点です。std::unique_ptrの場合、デリータの型をテンプレート引数に含める必要がありますが、std::shared_ptrは実行時にデリータを関数オブジェクトとして保持するため、異なるデリータを持つshared_ptr同士でも同じ型(std::shared_ptr)として扱うことができ、コンテナに混在させることが可能です。

3. 実装・解決策

std::shared_ptrのコンストラクタの第2引数に、ラムダ式や関数ポインタを渡すことでデリータを指定します。これにより、オブジェクトの寿命管理とリソースの解放を一元化できます。

4. サンプルプログラム

以下は、C言語の標準ライブラリ関数(malloc/free)で確保したメモリを管理する実用的な例です。


include
include
include

int main() {
// 1. mallocで確保したメモリをshared_ptrで管理する
// デフォルトのdeleteでは解放できないため、freeを呼ぶデリータを渡す
std::shared_ptr ptr(
static_cast(std::malloc(sizeof(int))),
[](int p) {
std::cout << "カスタムデリータ実行: メモリを解放します" << std::endl; std::free(p); } ); // 2. 正常に利用可能 ptr = 100; std::cout << "値: " << ptr << std::endl; // 3. スコープを抜けると自動的にカスタムデリータが呼ばれる return 0; }

5. 応用・注意点

実務で利用する際に気をつけるべきポイントを挙げます。

・循環参照の回避
カスタムデリータを使用しても、std::shared_ptr特有の循環参照の問題は発生します。相互参照が発生するような構造では、適宜std::weak_ptrを併用してください。

・デリータ内での例外送出
デリータ内から例外を投げることは避けてください。デリータは通常、デストラクタやスタックアンワインド中に呼ばれるため、例外が外に漏れるとプログラムがstd::terminateで即座に停止します。

・メモリ以外のリソース管理
データベースのコネクションや、RAIIに対応していないレガシーなAPIのハンドル管理にも応用できます。特に、複数の箇所でリソースを共有しつつ、最後の1つが破棄されたタイミングでクローズ処理を行いたい場合に、std::shared_ptrのカスタムデリータは非常に強力な武器となります。

コメント

タイトルとURLをコピーしました