【初心者向け】C++スマートポインタを使ってみよう
C++スマートポインタ入門(初心者向け)

C++で避けて通れないのがメモリ管理です。newで確保したメモリをdeleteし忘れたり、逆に二度解放してクラッシュさせてしまったり...。初心者がつまずきやすい箇所でもあります。
そんな問題を解決するために登場したのがスマートポインタです。
C++11以降の標準ライブラリに含まれており、今ではモダンC++の基本ツールになっています。
スマートポインタとは
スマートポインタは「ポインタっぽく使えるけれど、自動でメモリ解放してくれる」オブジェクトです。
スコープを抜けたときに自動でリソースを解放してくれるため、deleteを書き忘れる心配がなくなります。(なんと便利ですね...)
C++標準ライブラリでよく使われるのは次の3種類です。
unique_ptrshared_ptrweak_ptr
それぞれの役割と簡単な使い方を見ていきましょう。
unique_ptrについて
unique_ptrは、あるオブジェクトを一人で所有するスマートポインタです。
コピーはできませんが、所有権を別のunique_ptrに移すことは可能です。
#include <memory>
#include <iostream>
int main() {
std::unique_ptr<int> p = std::make_unique<int>(42);
std::cout << *p << std::endl; // 出力: 42
// コピーは不可
// std::unique_ptr<int> q = p; // コンパイルエラー
// 所有権を移す(ムーブ)
std::unique_ptr<int> q = std::move(p);
if (!p) {
std::cout << "pは所有権を失いました" << std::endl;
}
std::cout << *q << std::endl; // 出力: 42
}
ここで使っているstd::moveは「所有権を移す」ための仕組みです。
詳しくは 【初心者向け】C++ いい加減ムーブとコピーを理解しよう で解説しています。
shared_ptrについて
shared_ptrは、複数の所有者でリソースを共有できるスマートポインタです。
内部で「参照カウント」を持っており、最後の一人がいなくなった時点で解放されます。
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> a = std::make_shared<int>(100);
std::shared_ptr<int> b = a; // 共有
std::cout << *a << ", " << *b << std::endl; // 出力: 100, 100
std::cout << "参照カウント: " << a.use_count() << std::endl; // 出力: 2
a.reset(); // aが解放されてもbが残っているのでまだ有効
std::cout << *b << std::endl; // 出力: 100
}
ただし、shared_ptr同士でお互いを参照してしまうと循環参照が起き、メモリが解放されなくなることがあります。その場合に使うのが次のweak_ptrです。
weak_ptrについて
weak_ptrは、対象を所有せずに参照するためのポインタです。shared_ptrと組み合わせて循環参照を防ぐために使います。
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(200);
std::weak_ptr<int> wp = sp; // 所有しない参照
if (auto locked = wp.lock()) {
std::cout << "値: " << *locked << std::endl; // 出力: 200
}
sp.reset(); // 所有者がいなくなったので解放される
if (wp.expired()) {
std::cout << "オブジェクトはすでに解放されています" << std::endl;
}
}
lock()で一時的にshared_ptrを取得し、有効であればアクセスできます。所有者がすでにいなければexpired()がtrueになります。
まとめ
unique_ptr: 一人でリソースを所有するshared_ptr: みんなで共有するweak_ptr: 所有せず様子を見る
まずはこの3つの違いを理解しておけば十分です。
細かい仕組みは使いながら理解していけば問題ないので、ここでは「自動でdeleteしてくれる便利な道具」と覚えておきましょう。
スマートポインタを使うことで、C++のメモリ管理がずっと安全で楽になります。
