本文へスキップ
BecomeCoder

C++コース · 第16章 メモリ管理とスマートポインタ ― 漏らさない所有権 · レッスン65

std::unique_ptr ― 唯一の所有権

ブラウザで完結

導入

std::unique_ptr は「ある資源を、ただ1つのポインタだけが所有する」スマートポインタです。所有者がスコープを抜ければ自動で delete され、リークが起きません。最も基本で、まず第一候補にすべきスマートポインタです。

説明

<memory> を include し、make_unique<型>(引数) で作ります。ふつうのポインタと同じく *-> で使え、寿命が尽きると自動で解放されます。

#include <iostream>
#include <memory>
#include <string>
using namespace std;

class Dog {
public:
    string name;
    Dog(string n) : name(n) { cout << name << " 誕生" << endl; }
    ~Dog() { cout << name << " 解放" << endl; }
    void bark() { cout << name << ": ワン!" << endl; }
};

int main() {
    unique_ptr<Dog> p = make_unique<Dog>("ポチ");
    p->bark();              // -> でメンバにアクセス
    // delete は不要!
    return 0;               // ここで自動的に「ポチ 解放」
}
// ポチ 誕生 / ポチ: ワン! / ポチ 解放

unique_ptr は「唯一の所有」なのでコピーできません。所有権を別のポインタに渡すには std::move で「移動」します(第12章のムーブ)。移動後、元は空(nullptr)になります。

flowchart LR
  a["unique_ptr a(所有)"] -->|"std::move(a)"| b["unique_ptr b が所有へ"]
  a -.->|"移動後は空 nullptr"| x["(もう持っていない)"]
#include <iostream>
#include <memory>
using namespace std;

int main() {
    unique_ptr<int> a = make_unique<int>(100);
    // unique_ptr<int> b = a;        // ← エラー(コピー不可)
    unique_ptr<int> b = std::move(a);   // 所有権を移す
    cout << *b << endl;              // 100
    cout << (a == nullptr) << endl;  // 1(a は空になった)
    return 0;
}

まとめ

unique_ptr は「唯一の所有者」で、make_unique で作り、スコープを抜けると自動で解放します。コピー不可・std::move で所有権を移動。所有者が1人でよい場面(ほとんどの場面)では、これを最初に選びます。

実際に動かしてみよう

下のエディタにC++を書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のC++コンパイラ(clang + libc++)がその場でコンパイルして実行し、出力が表示されます。std::string・vector・クラス・テンプレート・STL などモダンC++がそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(cin)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。