【C++学習|初心者向け】std::unique_ptrの「削除子(Deleter)」を使いこなそう!get_deleter入門

1. 導入:メモリ管理をより柔軟にするために

C++のstd::unique_ptrは、スコープを抜けると自動的にメモリを解放してくれる非常に便利なツールです。しかし、標準的なdelete処理だけでは対応できないケースがあります。例えば、「C言語のAPIで確保したメモリをfreeで解放したい」「ファイルハンドルを閉じる処理を自動化したい」といった場合です。そんな時、独自の解放ルール(削除子)を定義することで解決できます。今回は、その削除子を操作するためのget_deleterメソッドについて解説します。

2. 基礎知識:削除子(Deleter)とは?

通常、unique_ptrはdelete演算子を使ってメモリを解放します。しかし、テンプレート引数を指定することで、この「解放ルール」を自由に変更できます。これが「削除子」です。
削除子は関数オブジェクトやラムダ式として定義でき、unique_ptrが破棄されるタイミングで自動的に呼び出されます。get_deleter関数を使うと、現在そのunique_ptrに設定されている削除子そのものを取り出して操作することができます。

3. 実装/解決策:get_deleterの使い方

get_deleterは、unique_ptrが保持している削除子オブジェクトのポインタを返します。これを使うことで、実行時に削除子の状態を確認したり、動的に設定を変更したりすることが可能です。
注意点として、get_deleterはテンプレート引数に「削除子の型」を指定する必要があります。

4. サンプルプログラム

以下のコードは、カスタム削除子を持つunique_ptrから、get_deleterを使って削除子を取得し、その内部状態を確認する例です。

include
include

// カスタム削除子の定義
struct MyDeleter {
int count = 0; // 解放回数をカウントする変数
void operator()(int p) {
std::cout << "メモリを解放します。" << std::endl; delete p; count++; } }; int main() { // 削除子を指定してunique_ptrを作成 std::unique_ptr ptr(new int(10));

// get_deleterで削除子を取得する(型を指定する必要がある)
// 戻り値はポインタなので、nullptrチェックを行うのが安全
auto deleter = std::get_deleter(ptr);

if (deleter) {
std::cout << "現在の解放回数: " << deleter->count << std::endl; } return 0; // ここでptrが破棄され、削除子が実行される }

5. 応用・注意点:現場での活用と落とし穴

注意点1:型の一致
get_deleterを使用する際、テンプレート引数に指定する型が、unique_ptr作成時に指定した削除子の型と完全に一致している必要があります。一致していない場合、nullptrが返されます。

注意点2:所有権の移動
unique_ptrの所有権をstd::moveで移動させると、削除子も一緒に移動します。get_deleterで取得したポインタは、あくまでその時点でのunique_ptrの状態を参照しているだけですので、unique_ptrの寿命が切れた後にそのポインタを使い回さないよう注意してください。

応用:
独自のログ出力機能を持つ削除子を作成し、get_deleter経由で「現在までに何個のオブジェクトを解放したか」をデバッグ情報として出力するといった使い方が、現場では重宝されます。メモリ管理の「自動化」と「可視化」を両立できるのが、この機能の最大の強みです。

コメント

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