次の方法で共有


shared_ptr クラス

参照カウント スマート ポインターを、動的に割り当てられたオブジェクトにラップします。

構文

template <class T>
class shared_ptr;

解説

shared_ptr クラスは、参照カウントを使ってリソースを管理するオブジェクトを表します。 shared_ptr オブジェクトは、所有しているリソースへのポインターまたは null ポインターを効率的に保持します。 複数の shared_ptr オブジェクトが 1 つのリソースを所有することもできます。その場合、特定のリソースを所有する最後の shared_ptr オブジェクトが破棄された時点で、リソースが解放されます。

shared_ptr は、再割り当てまたはリセットされるとリソースの所有を停止します。

テンプレートの引数 T は、特定のメンバー関数について注記がある場合を除き、不完全な型になる場合があります。

shared_ptr<T> オブジェクトを G* 型のリソース ポインターまたは shared_ptr<G> から構築する場合、ポインターの型 G*T* に変換可能であることが必要です。 変換できない場合、コードはコンパイルされません。 次に例を示します。

#include <memory>
using namespace std;

class F {};
class G : public F {};

shared_ptr<G> sp0(new G);   // okay, template parameter G and argument G*
shared_ptr<G> sp1(sp0);     // okay, template parameter G and argument shared_ptr<G>
shared_ptr<F> sp2(new G);   // okay, G* convertible to F*
shared_ptr<F> sp3(sp0);     // okay, template parameter F and argument shared_ptr<G>
shared_ptr<F> sp4(sp2);     // okay, template parameter F and argument shared_ptr<F>
shared_ptr<int> sp5(new G); // error, G* not convertible to int*
shared_ptr<int> sp6(sp2);   // error, template parameter int and argument shared_ptr<F>

shared_ptr オブジェクトがリソースを所有するためには、次のいずれかの条件を満たしている必要があります。

  • そのリソースへのポインターを使って構築されている。

  • そのリソースを所有する shared_ptr オブジェクトから構築されている。

  • そのリソースを指し示す weak_ptr オブジェクトから構築されている。

  • そのリソースの所有権が、shared_ptr::operator= またはメンバー関数 shared_ptr::reset の呼び出しのいずれかによって割り当てられている。

リソースを所有する shared_ptr オブジェクトは、コントロール ブロックを共有します。 コントロール ブロックは以下の情報を保持します。

  • リソースを所有する shared_ptr オブジェクトの数。

  • リソースを指す weak_ptr オブジェクトの数。

  • リソースの削除子 (存在する場合)

  • コントロール ブロックのカスタム アロケーター (存在する場合)

null ポインターを使用して初期化された shared_ptr オブジェクトには制御ブロックがあり、空ではありません。 shared_ptr オブジェクトがリソースを所有するのは、そのリソースが解放されるまでの間です。 weak_ptr オブジェクトがリソースを指しているのは、そのリソースが解放されるまでの間です。

リソースを所有する shared_ptr オブジェクトの数がゼロになると、リソースを削除するか、リソースのアドレスを削除子に渡すことによって、リソースが解放されます。どちらの方法で解放されるかは、最初にリソースの所有権が作成された方法によって決定されます。 リソースを所有する shared_ptr オブジェクトの数がゼロになり、そのリソースを指す weak_ptr オブジェクトの数がゼロになると、コントロール ブロックのカスタム アロケーターを使用して (存在する場合)、コントロール ブロックが解放されます。

空の shared_ptr オブジェクトはリソースを所有せず、制御ブロックもありません。

削除子は、メンバー関数 operator() を持つ関数オブジェクトです。 この型はコピーによって構築可能であること、また、コピー コンストラクターおよびデストラクターによって例外がスローされないことが必要です。 削除子は、削除するオブジェクトを指定する 1 つのパラメーターを受け入れます。

一部の関数では、結果として生成される shared_ptr<T> または weak_ptr<T> オブジェクトのプロパティを定義する引数リストが使用されます。 その場合、引数リストは次のような方法で指定できます。

引数なし: 結果のオブジェクトは、空の shared_ptr オブジェクトまたは空の weak_ptr オブジェクトです。

ptr: マネージドするリソースに Other* 型のポインター。 T は完全な型である必要があります。 コントロール ブロックを割り当てることができなかったことが原因で関数が失敗した場合、式 delete ptr が評価されます。

ptr, deleter: マネージドするリソースと、そのリソースの deleter に Other* 型のポインター。 コントロール ブロックを割り当てることができなかったことが原因で関数が失敗した場合、deleter(ptr) が呼び出されます (明確に定義されていることが必要)。

ptr, deleter, alloc: マネージドするリソースに Other* 型のポインター、そのリソースの削除ツール、および割り当てと解放が必要なストレージを管理するためのアロケーター。 コントロール ブロックを割り当てることができなかったことが原因で関数が失敗した場合、deleter(ptr) が呼び出されます (明確に定義されていることが必要)。

sp: 管理するリソースを所有する shared_ptr<Other> オブジェクト。

wp: 管理するリソースを指す weak_ptr<Other> オブジェクト。

ap: 管理するリソースへのポインターを保持する auto_ptr<Other> オブジェクト。 関数が成功した場合は、ap.release() が呼び出されます。関数が失敗した場合は、ap は変更されません。

いずれの場合も、ポインターの型 Other*T* に変換可能である必要があります。

スレッド セーフ

複数のスレッドが異なる shared_ptr オブジェクト (所有権を共有するコピーである場合も含めて) に対する読み取りと書き込みを同時に行うことができます。

メンバー

名前 説明
コンストラクター
shared_ptr shared_ptr を構築します。
~shared_ptr shared_ptr を破棄します。
Typedefs
element_type 要素の型。
weak_type 要素への弱いポインターの型。
メンバー関数
get 所有されているリソースのアドレスを取得します。
owner_before この shared_ptr が、指定されたポインターの前に順序付けされている (またはそれよりも少ない) 場合は true を返します。
reset 所有されたリソースを置き換えます。
swap 2 つの shared_ptr オブジェクトを交換します。
unique 所有されたリソースが一意であるかどうかをテストします。
use_count リソース所有者の数をカウントします。
演算子
operator bool 所有されたリソースが存在するかどうかをテストします。
operator* 指定された値を取得します。
operator= 所有されたリソースを置き換えます。
operator-> 指定された値へのポインターを取得します。

element_type

要素の型。

typedef T element_type;                  // before C++17
using element_type = remove_extent_t<T>; // C++17

解説

element_type 型は、テンプレート パラメーター T のシノニムです。

// std__memory__shared_ptr_element_type.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0(new int(5));
    std::shared_ptr<int>::element_type val = *sp0;

    std::cout << "*sp0 == " << val << std::endl;

    return (0);
}
*sp0 == 5

get

所有されているリソースのアドレスを取得します。

element_type* get() const noexcept;

解説

メンバー関数は、所有されたリソースのアドレスを返します。 オブジェクトがリソースを所有していない場合は、0 を返します。

// std__memory__shared_ptr_get.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));

    std::cout << "sp0.get() == 0 == " << std::boolalpha
        << (sp0.get() == 0) << std::endl;
    std::cout << "*sp1.get() == " << *sp1.get() << std::endl;

    return (0);
}
sp0.get() == 0 == true
*sp1.get() == 5

operator bool

所有されたリソースが存在するかどうかをテストします。

explicit operator bool() const noexcept;

解説

演算子は、get() != nullptr の場合は true の値を返し、それ以外の場合は false を返します。

// std__memory__shared_ptr_operator_bool.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));

    std::cout << "(bool)sp0 == " << std::boolalpha
        << (bool)sp0 << std::endl;
    std::cout << "(bool)sp1 == " << std::boolalpha
        << (bool)sp1 << std::endl;

    return (0);
}
(bool)sp0 == false
(bool)sp1 == true

operator*

指定された値を取得します。

T& operator*() const noexcept;

解説

間接演算子は *get() を返します。 つまり、格納されたポインターは、null にすることはできません。

// std__memory__shared_ptr_operator_st.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0(new int(5));

    std::cout << "*sp0 == " << *sp0 << std::endl;

    return (0);
}
*sp0 == 5

operator=

所有されたリソースを置き換えます。

shared_ptr& operator=(const shared_ptr& sp) noexcept;

shared_ptr& operator=(shared_ptr&& sp) noexcept;

template <class Other>
shared_ptr& operator=(const shared_ptr<Other>& sp) noexcept;

template <class Other>
shared_ptr& operator=(shared_ptr<Other>&& sp) noexcept;

template <class Other>
shared_ptr& operator=(auto_ptr<Other>&& ap);    // deprecated in C++11, removed in C++17

template <class Other, class Deleter>
shared_ptr& operator=(unique_ptr<Other, Deleter>&& up);

パラメーター

sp
コピーまたは移動する共有ポインター。

ap
移動する自動ポインター。 auto_ptr オーバーロードは C++11 では非推奨とされ、C++17 では削除されます。

up
所有権を採用するオブジェクトへの一意のポインター。 up は、呼び出し後にオブジェクトを所有しません。

Other
spap、または up によって指されるオブジェクトの型。

Deleter
後でオブジェクトを削除する場合に格納される、所有オブジェクトの削除子の型。

解説

すべての演算子は、現在 *this によって所有されているリソースの参照数をデクリメントし、オペランド シーケンスで指定されたリソースの所有権を *this に割り当てます。 参照数がゼロになる場合は、リソースが解放されます。 演算子が失敗した場合、*this は変更されません。

// std__memory__shared_ptr_operator_as.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));
    std::unique_ptr<int> up(new int(10));

    sp0 = sp1;
    std::cout << "*sp0 == " << *sp0 << std::endl;

    sp0 = up;
    std::cout << "*sp0 == " << *sp0 << std::endl;

    return (0);
}
*sp0 == 5
*sp0 == 10

operator->

指定された値へのポインターを取得します。

T* operator->() const noexcept;

解説

sp がクラス shared_ptr<T> のオブジェクトである場合に式 sp->member(sp.get())->member と同様に動作するよう、選択演算子は get() を返します。 そのため、格納されているポインターを null にすることはできず、T はメンバー member を持つクラス、構造体、または共用体型にする必要があります。

// std__memory__shared_ptr_operator_ar.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

typedef std::pair<int, int> Mypair;
int main()
{
    std::shared_ptr<Mypair> sp0(new Mypair(1, 2));

    std::cout << "sp0->first == " << sp0->first << std::endl;
    std::cout << "sp0->second == " << sp0->second << std::endl;

    return (0);
}
sp0->first == 1
sp0->second == 2

owner_before

この shared_ptr が、指定されたポインターの前に順序付けされている (またはそれよりも少ない) 場合は true を返します。

template <class Other>
bool owner_before(const shared_ptr<Other>& ptr) const noexcept;

template <class Other>
bool owner_before(const weak_ptr<Other>& ptr) const noexcept;

パラメーター

ptr
shared_ptr または weak_ptr への左辺値参照。

解説

テンプレート メンバー関数は、*thisptr の前にある場合に true を返します。

reset

所有されたリソースを置き換えます。

void reset() noexcept;

template <class Other>
void reset(Other *ptr);

template <class Other, class Deleter>
void reset(
    Other *ptr,
    Deleter deleter);

template <class Other, class Deleter, class Allocator>
void reset(
    Other *ptr,
    Deleter deleter,
    Allocator alloc);

パラメーター

Other
引数ポインターによって制御される型。

Deleter
削除子の型。

ptr
コピーするポインター。

deleter
コピーする削除子。

Allocator
アロケーターの型。

alloc
コピーするアロケーター。

解説

すべての演算子は、現在 *this によって所有されているリソースの参照数をデクリメントし、オペランド シーケンスで指定されたリソースの所有権を *this に割り当てます。 参照数がゼロになる場合は、リソースが解放されます。 演算子が失敗した場合、*this は変更されません。

// std__memory__shared_ptr_reset.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

struct deleter
{
    void operator()(int *p)
    {
        delete p;
    }
};

int main()
{
    std::shared_ptr<int> sp(new int(5));

    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    sp.reset();
    std::cout << "(bool)sp == " << std::boolalpha
        << (bool)sp << std::endl;

    sp.reset(new int(10));
    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    sp.reset(new int(15), deleter());
    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    return (0);
}
*sp == 5
(bool)sp == false
*sp == 10
*sp == 15

shared_ptr

shared_ptr を構築します。

constexpr shared_ptr() noexcept;

constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() {}

shared_ptr(const shared_ptr& sp) noexcept;

shared_ptr(shared_ptr&& sp) noexcept;

template <class Other>
explicit shared_ptr(Other* ptr);

template <class Other, class Deleter>
shared_ptr(
    Other* ptr,
    Deleter deleter);

template <class Deleter>
shared_ptr(
    nullptr_t ptr,
    Deleter deleter);

template <class Other, class Deleter, class Allocator>
shared_ptr(
    Other* ptr,
    Deleter deleter,
    Allocator alloc);

template <class Deleter, class Allocator>
shared_ptr(
    nullptr_t ptr,
    Deleter deleter,
    Allocator alloc);

template <class Other>
shared_ptr(
    const shared_ptr<Other>& sp) noexcept;

template <class Other>
explicit shared_ptr(
    const weak_ptr<Other>& wp);

template <class &>
shared_ptr(
    std::auto_ptr<Other>& ap);

template <class &>
shared_ptr(
    std::auto_ptr<Other>&& ap);

template <class Other, class Deleter>
shared_ptr(
    unique_ptr<Other, Deleter>&& up);

template <class Other>
shared_ptr(
    const shared_ptr<Other>& sp,
    element_type* ptr) noexcept;

template <class Other>
shared_ptr(
    shared_ptr<Other>&& sp,
    element_type* ptr) noexcept;

template <class Other, class Deleter>
shared_ptr(
    const unique_ptr<Other, Deleter>& up) = delete;

パラメーター

Other
引数ポインターによって制御される型。

ptr
コピーするポインター。

Deleter
削除子の型。

Allocator
アロケーターの型。

deleter
削除子。

alloc
アロケーター。

sp
コピーするスマート ポインター。

wp
ウィーク ポインター。

ap
コピーする自動ポインター。

解説

それぞれのコンストラクターは、オペランド シーケンスで指定されたリソースを所有するオブジェクトを構築します。 コンストラクター shared_ptr(const weak_ptr<Other>& wp) は、wp.expired() の場合、型 bad_weak_ptr の例外オブジェクトをスローします。

// std__memory__shared_ptr_construct.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

struct deleter
{
    void operator()(int *p)
    {
        delete p;
    }
};

int main()
{
    std::shared_ptr<int> sp0;
    std::cout << "(bool)sp0 == " << std::boolalpha
        << (bool)sp0 << std::endl;

    std::shared_ptr<int> sp1(new int(5));
    std::cout << "*sp1 == " << *sp1 << std::endl;

    std::shared_ptr<int> sp2(new int(10), deleter());
    std::cout << "*sp2 == " << *sp2 << std::endl;

    std::shared_ptr<int> sp3(sp2);
    std::cout << "*sp3 == " << *sp3 << std::endl;

    std::weak_ptr<int> wp(sp3);
    std::shared_ptr<int> sp4(wp);
    std::cout << "*sp4 == " << *sp4 << std::endl;

    std::auto_ptr<int> ap(new int(15));
    std::shared_ptr<int> sp5(ap);
    std::cout << "*sp5 == " << *sp5 << std::endl;

    return (0);
}
(bool)sp0 == false
*sp1 == 5
*sp2 == 10
*sp3 == 10
*sp4 == 10
*sp5 == 15

~shared_ptr

shared_ptr を破棄します。

~shared_ptr();

解説

デストラクターは、現在 *this によって所有されるリソースの参照数をデクリメントします。 参照数がゼロになる場合は、リソースが解放されます。

// std__memory__shared_ptr_destroy.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "*sp1 == " << *sp1 << std::endl;
    std::cout << "use count == " << sp1.use_count() << std::endl;

    {
        std::shared_ptr<int> sp2(sp1);
        std::cout << "*sp2 == " << *sp2 << std::endl;
        std::cout << "use count == " << sp1.use_count() << std::endl;
    }

    // check use count after sp2 is destroyed
    std::cout << "use count == " << sp1.use_count() << std::endl;

    return (0);
}
*sp1 == 5
use count == 1
*sp2 == 5
use count == 2
use count == 1

swap

2 つの shared_ptr オブジェクトを交換します。

void swap(shared_ptr& sp) noexcept;

パラメーター

sp
交換先の共有ポインター。

解説

メンバー関数は、最初に *this が所有してその後 sp が所有するリソースと、最初に sp が所有してその後 *this が所有するリソースを残します。 この関数はこれら 2 つのリソースの参照数を変更せず、例外をスローしません。

// std__memory__shared_ptr_swap.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::shared_ptr<int> sp2(new int(10));
    std::cout << "*sp1 == " << *sp1 << std::endl;

    sp1.swap(sp2);
    std::cout << "*sp1 == " << *sp1 << std::endl;

    swap(sp1, sp2);
    std::cout << "*sp1 == " << *sp1 << std::endl;
    std::cout << std::endl;

    std::weak_ptr<int> wp1(sp1);
    std::weak_ptr<int> wp2(sp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    wp1.swap(wp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    swap(wp1, wp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    return (0);
}
*sp1 == 5
*sp1 == 10
*sp1 == 5
*wp1 == 5
*wp1 == 10
*wp1 == 5

unique

所有されたリソースが一意であるかどうかをテストします。 この関数は C++ 17 で非推奨とされ、C++ 20 で削除されました。

bool unique() const noexcept;

解説

メンバー関数は、*this が所有するリソースを所有する shared_ptr オブジェクトが他にない場合に true を返し、それ以外の場合は false を返します。

// std__memory__shared_ptr_unique.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "sp1.unique() == " << std::boolalpha
        << sp1.unique() << std::endl;

    std::shared_ptr<int> sp2(sp1);
    std::cout << "sp1.unique() == " << std::boolalpha
        << sp1.unique() << std::endl;

    return (0);
}
sp1.unique() == true
sp1.unique() == false

use_count

リソース所有者の数をカウントします。

long use_count() const noexcept;

解説

メンバー関数は、*this が所有するリソースを所有する shared_ptr オブジェクトの数を返します。

// std__memory__shared_ptr_use_count.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "sp1.use_count() == "
        << sp1.use_count() << std::endl;

    std::shared_ptr<int> sp2(sp1);
    std::cout << "sp1.use_count() == "
        << sp1.use_count() << std::endl;

    return (0);
}
sp1.use_count() == 1
sp1.use_count() == 2

weak_type

要素への弱いポインターの型。

using weak_type = weak_ptr<T>; // C++17

解説

weak_type 定義は C++17 で追加されました。

関連項目

ヘッダー ファイル リファレンス
<memory>
unique_ptr
weak_ptr クラス