名前空間
変種
操作

std::unique_ptr

提供: cppreference.com
< cpp‎ | memory
 
 
 
動的メモリ管理
未初期化記憶域
(C++17)
(deprecated since c++17)
(deprecated since c++17)
(deprecated since c++17)
ガベージコレクションサポート
その他
(C++20)
(C++11)
(C++11)
C のライブラリ
低水準のメモリ管理
 
 
ヘッダ <memory> で定義
template<

    class T,
    class Deleter = std::default_delete<T>

> class unique_ptr;
(1) (C++11およびそれ以降)
template <

    class T,
    class Deleter

> class unique_ptr<T[], Deleter>;
(2) (C++11およびそれ以降)

std::unique_ptr はポインタを通して他のオブジェクトを所有、管理し、スコープから外れたときにそのオブジェクトを処分するスマートポインタです。

以下のいずれかが発生したとき、紐付けられたデリータを使用してオブジェクトが処分されます。

  • 管理している unique_ptr オブジェクトが破棄された
  • 管理している unique_ptr オブジェクトが operator= または reset() を通して他のポインタから代入された

オブジェクトは、 get_deleter()(ptr) を呼ぶことによって、デフォルトのまたはユーザ提供のデリータを使用して処分されます。 デフォルトのデリータは delete 演算子を使用してオブジェクトを破棄し、メモリを解放します。

unique_ptr は何のオブジェクトも所有しないこともあります。 この場合は「空」と呼ばれます。

std::unique_ptr には2つのバージョンがあります。

1) 単一のオブジェクトを管理するもの (例えば new で確保されたもの)
2) 動的確保されたオブジェクトの配列を管理するもの (例えば new[] で確保されたもの)

このクラスは MoveConstructible および MoveAssignable の要件を満たしますが、 CopyConstructible および CopyAssignable はいずれも満たしません。

型の要件
-
Deleterunique_ptr<T, Deleter>::pointer 型の引数で呼び出せる FunctionObject または FunctionObject への左辺値参照または関数への左辺値参照でなければなりません。

目次

[編集] ノート

非 const な unique_ptr だけが管理対象オブジェクトの所有権を他の unique_ptr に転送できます。 オブジェクトの存在期間が const std::unique_ptr によって管理されている場合、それはそのポインタが作成されたスコープに限定されます。

std::unique_ptr はオブジェクトの存在期間を管理するためによく使われます。 例えば、

  • 正常終了および例外による終了の両方で削除されることを保証することによって、動的存在期間を持つオブジェクトを扱うクラスおよび関数に例外安全性を提供する場合
  • 唯一的に所有された動的存在期間を持つオブジェクトの所有権を関数に渡す場合
  • 唯一的に所有された同的存在期間を持つオブジェクトの所有権を関数から取得する場合
  • ムーブ対応コンテナ、例えば std::vector の要素型として、動的確保されたオブジェクトへのポインタを保持する場合 (多相的な動作が求められる場合など)

std::unique_ptr不完全型 T に対して構築できます。 例えば pImpl イディオムでハンドルとしての使用を容易にします。 デフォルトのデリータを使用する場合、 T はコード中のデリータが呼び出される時点で完全でなければなりません。 これは std::unique_ptr のデストラクタ、ムーブ代入演算子、 reset メンバ関数で発生します (それに対して、 std::shared_ptr は不完全型に対する生のポインタから構築することはできませんが、 T が不完全な場所でも破棄できます)。 ちなみに、 T がクラステンプレートの特殊化である場合、 unique_ptr を被演算子として使用するにあたっては (例えば !p)、 ADL のため、 T の引数が完全であることが要求されます。

T が何らかの基底クラス B派生クラスである場合、 std::unique_ptr<T>std::unique_ptr<B>暗黙に変換できます。 結果の std::unique_ptr<B> のデフォルトのデリータは B に対する operator delete を使用するので、 B のデストラクタが virtual でなければ、未定義動作に繋がります。 ちなみに、 std::shared_ptr は異なる動作をします。 std::shared_ptr<B> は、 B のデストラクタが virtual でなくとも、型 T に対する operator delete を使用し、所有オブジェクトを正しく削除します。

std::shared_ptr と異なり、 std::unique_ptrNullablePointer を満たす任意のカスタムハンドル型を通してオブジェクトを管理することができます。 これにより、例えば typedef boost::offset_ptr pointer; または他のファンシーポインタを定義する Deleter を提供することによって、共有メモリに配置されているオブジェクトを管理したりできます。

[編集] メンバ型

メンバ型 定義
pointer std::remove_reference<Deleter>::type::pointer が存在すればその型、そうでなければ T*NullablePointer を満たさなければなりません
element_type この unique_ptr によって管理されるオブジェクトの型 T
deleter_type デストラクタから呼ばれるための関数オブジェクトまたは関数への左辺値参照または関数オブジェクトへの左辺値参照 Deleter

[編集] メンバ関数

新しい unique_ptr を構築します
(パブリックメンバ関数) [edit]
管理対象オブジェクト存在すれば、それを破棄します
(パブリックメンバ関数) [edit]
unique_ptr を代入します
(パブリックメンバ関数) [edit]
変更
管理対象オブジェクトへのポインタを返し、所有権を解放します
(パブリックメンバ関数) [edit]
管理対象オブジェクトを置き換えます
(パブリックメンバ関数) [edit]
管理対象オブジェクトを入れ替えます
(パブリックメンバ関数) [edit]
観察
管理対象オブジェクトへのポインタを返します
(パブリックメンバ関数) [edit]
管理対象オブジェクトを破棄するために使用されるデリータを返します
(パブリックメンバ関数) [edit]
紐付けられた管理対象オブジェクトが存在するかどうか確認します
(パブリックメンバ関数) [edit]
単一オブジェクト版の unique_ptr<T>
管理対象オブジェクトへのポインタを逆参照します
(パブリックメンバ関数) [edit]
配列版の unique_ptr<T[]>
管理対象配列へのインデックスアクセスを提供します
(パブリックメンバ関数) [edit]

[編集] 非メンバ関数

新しいオブジェクトを管理する unique_ptr を作成します
(関数テンプレート) [edit]
別の unique_ptr または nullptr と比較します
(関数テンプレート) [edit]
管理対象オブジェクトの値を出力ストリームに出力します
(関数テンプレート) [edit]
std::swap アルゴリズムの特殊化
(関数テンプレート) [edit]

[編集] ヘルパークラス

std::unique_ptr に対するハッシュサポート
(クラステンプレートの特殊化) [edit]

[編集]

#include <iostream>
#include <vector>
#include <memory>
#include <cstdio>
#include <fstream>
#include <cassert>
#include <functional>
 
struct B {
  virtual void bar() { std::cout << "B::bar\n"; }
  virtual ~B() = default;
};
struct D : B
{
    D() { std::cout << "D::D\n";  }
    ~D() { std::cout << "D::~D\n";  }
    void bar() override { std::cout << "D::bar\n";  }
};
 
// a function consuming a unique_ptr can take it by value or by rvalue reference
std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
{
    p->bar();
    return p;
}
 
void close_file(std::FILE* fp) { std::fclose(fp); }
 
int main()
{
  std::cout << "unique ownership semantics demo\n";
  {
      auto p = std::make_unique<D>(); // p is a unique_ptr that owns a D
      auto q = pass_through(std::move(p)); 
      assert(!p); // now p owns nothing and holds a null pointer
      q->bar();   // and q owns the D object
  } // ~D called here
 
  std::cout << "Runtime polymorphism demo\n";
  {
    std::unique_ptr<B> p = std::make_unique<D>(); // p is a unique_ptr that owns a D
                                                  // as a pointer to base
    p->bar(); // virtual dispatch
 
    std::vector<std::unique_ptr<B>> v;  // unique_ptr can be stored in a container
    v.push_back(std::make_unique<D>());
    v.push_back(std::move(p));
    v.emplace_back(new D);
    for(auto& p: v) p->bar(); // virtual dispatch
  } // ~D called 3 times
 
  std::cout << "Custom deleter demo\n";
  std::ofstream("demo.txt") << 'x'; // prepare the file to read
  {
      std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt", "r"),
                                                           &close_file);
      if(fp) // fopen could have failed; in which case fp holds a null pointer
        std::cout << (char)std::fgetc(fp.get()) << '\n';
  } // fclose() called here, but only if FILE* is not a null pointer
    // (that is, if fopen succeeded)
 
  std::cout << "Custom lambda-expression deleter demo\n";
  {
    std::unique_ptr<D, std::function<void(D*)>> p(new D, [](D* ptr)
        {
            std::cout << "destroying from a custom deleter...\n";
            delete ptr;
        });  // p owns D
    p->bar();
  } // the lambda above is called and D is destroyed
 
  std::cout << "Array form of unique_ptr demo\n";
  {
      std::unique_ptr<D[]> p{new D[3]};
  } // calls ~D 3 times
}

出力:

unique ownership semantics demo
D::D
D::bar
D::bar
D::~D
Runtime polymorphism demo
D::D
D::bar
D::D
D::D
D::bar
D::bar
D::bar
D::~D
D::~D
D::~D
Custom deleter demo
x
Custom lambda-expression deleter demo
D::D
D::bar
destroying from a custom deleter...
D::~D
Array form of unique_ptr demo
D::D
D::D
D::D
D::~D
D::~D
D::~D