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
sp
、ap
、または 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
への左辺値参照。
解説
テンプレート メンバー関数は、*this
が ptr
の前にある場合に 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 で追加されました。