namespace std {
template <class T>
class shared_ptr;
}
概要
shared_ptr
は、指定されたリソースへの所有権(ownership)を共有(share)するスマートポインタである。
複数のshared_ptr
オブジェクトが同じリソースを共有し、所有者が0人、つまりどのshared_ptr
オブジェクトからもリソースが参照されなくなると、リソースが自動的に解放される。
参照カウント
shared_ptr
は「参照カウント(reference count)」によって実装される。
shared_ptr
オブジェクトのコピー構築、コピー代入が行われるとカウントが1増える。デストラクタが実行されるとカウントが1減る。そしてカウントが0になると、自動的に「delete p;
」が実行され、リソースが解放される。
スレッド安全性
shared_ptr
の参照カウンタはスレッドセーフである。つまり、スレッドを跨いでshared_ptr
をコピーし、リソースを共有することが安全にできる。
非スレッドセーフに参照カウントを増減させる方法はない。シングルスレッドでのパフォーマンスが重要で、スレッドセーフであることによるオーバーヘッドが問題になる場合、ムーブを活用すればパフォーマンスを改善できる。
メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++11 |
(destructor) |
デストラクタ | C++11 |
operator= |
代入演算子 | C++11 |
reset |
所有権を放棄し、新たな所有権を設定する | C++11 |
swap |
他のshared_ptr オブジェクトとデータを入れ替える |
C++11 |
get |
リソースを取得する | C++11 |
operator* |
間接参照 | C++11 |
operator-> |
メンバアクセス | C++11 |
operator[] |
添字による要素アクセス | C++17 |
use_count |
所有権を持つユーザー数を取得する | C++11 |
unique |
所有権を持つユーザーが一人だけかを判定する | C++11 C++17から非推奨 C++20で削除 |
operator bool |
有効なリソースを所有しているかを判定する | C++11 |
owner_before |
所有権ベースでの小なり比較を行う | C++11 |
メンバ型
名前 | 説明 | 対応バージョン |
---|---|---|
element_type |
管理するインスタンスの型 C++11 : T C++17 : remove_extent_t<T> |
C++11 |
weak_type |
弱参照ポインタの型weak_ptr<T> |
C++17 |
非メンバ関数
名前 | 説明 | 対応バージョン |
---|---|---|
operator== |
等値比較 | C++11 |
operator!= |
非等値比較 | C++11 |
operator<=> |
三方比較 | C++20 |
operator< |
左辺が右辺より小さいかを判定する | C++11 |
operator<= |
左辺が右辺以下かを判定する | C++11 |
operator> |
左辺が右辺より大きいかを判定する | C++11 |
operator>= |
左辺が右辺以上かを判定する | C++11 |
swap |
2つのshared_ptr オブジェクトを入れ替える |
C++11 |
get_deleter |
デリータを取得する | C++11 |
operator<< |
ストリームへの出力 | C++11 |
static_pointer_cast |
shared_ptr の静的キャスト |
C++11 |
dynamic_pointer_cast |
shared_ptr の動的キャスト |
C++11 |
const_pointer_cast |
shared_ptr のconst 修飾キャスト |
C++11 |
reinterpret_pointer_cast |
shared_ptr の再解釈キャスト |
C++17 |
make_shared |
shared_ptr を構築するヘルパ関数 |
C++11 |
allocate_shared |
アロケータを指定してshared_ptr を構築するヘルパ関数 |
C++11 |
アトミックアクセス(非メンバ関数)
名前 | 説明 | 対応バージョン |
---|---|---|
atomic_is_lock_free |
指定されたオブジェクトがロックフリーに振る舞えるかを調べる | C++11 C++20から非推奨 C++26で削除 |
atomic_store |
値を書き込む | C++11 C++20から非推奨 C++26で削除 |
atomic_store_explicit |
メモリオーダーを指定して値を書き込む | C++11 C++20から非推奨 C++26で削除 |
atomic_load |
値を読み込む | C++11 C++20から非推奨 C++26で削除 |
atomic_load_explicit |
メモリオーダーを指定して値を読み込む | C++11 C++20から非推奨 C++26で削除 |
atomic_exchange |
値を入れ替える | C++11 C++20から非推奨 C++26で削除 |
atomic_exchange_explicit |
メモリオーダーを指定して値を入れ替える | C++11 C++20から非推奨 C++26で削除 |
atomic_compare_exchange_weak |
弱い比較で値の入れ替えを行う | C++11 C++20から非推奨 C++26で削除 |
atomic_compare_exchange_strong |
強い比較で値の入れ替えを行う | C++11 C++20から非推奨 C++26で削除 |
atomic_compare_exchange_weak_explicit |
弱い比較でメモリオーダーを指定して値の入れ替えを行う | C++11 C++20から非推奨 C++26で削除 |
atomic_compare_exchange_strong_explicit |
強い比較でメモリオーダーを指定して値の入れ替えを行う | C++11 C++20から非推奨 C++26で削除 |
ハッシュサポート
名前 | 説明 | 対応バージョン |
---|---|---|
template <class T> struct hash; |
hash クラスの先行宣言 |
C++11 |
template <class T> struct hash<shared_ptr<T>>; |
hash クラスのshared_ptr に対する特殊化 |
C++11 |
推論補助
名前 | 説明 | 対応バージョン |
---|---|---|
(deduction_guide) |
クラステンプレートの推論補助 | C++17 |
例
shared_ptrの基本的な使い方
#include <iostream>
#include <memory>
int main()
{
// newしたポインタをshared_ptrオブジェクトに管理させる
// 所有者は1人。
std::shared_ptr<int> p1(new int(3));
{
// shared_ptrオブジェクトをコピーすることで、
// 複数のオブジェクトが一つのリソースを共有できる。
// 所有者が2人になる。
std::shared_ptr<int> p2 = p1;
// 共有しているリソースにアクセスする
std::cout << *p2 << std::endl;
} // p2のデストラクタが実行される。
// リソースの所有者が1人になる。
// ここではまだ、リソースは解放されない。
std::cout << *p1 << std::endl;
} // p1のデストラクタが実行される。
// リソースの所有者が0人になる。
// 誰もリソースを参照しなくなったので、リソースが解放される。
xxxxxxxxxx
#include <iostream>
#include <memory>
int main()
{
// newしたポインタをshared_ptrオブジェクトに管理させる
// 所有者は1人。
std::shared_ptr<int> p1(new int(3));
{
// shared_ptrオブジェクトをコピーすることで、
// 複数のオブジェクトが一つのリソースを共有できる。
// 所有者が2人になる。
std::shared_ptr<int> p2 = p1;
// 共有しているリソースにアクセスする
std::cout << *p2 << std::endl;
} // p2のデストラクタが実行される。
// リソースの所有者が1人になる。
// ここではまだ、リソースは解放されない。
std::cout << *p1 << std::endl;
} // p1のデストラクタが実行される。
// リソースの所有者が0人になる。
// 誰もリソースを参照しなくなったので、リソースが解放される。
出力
3
3
shared_ptr<void>に、あらゆる型のポインタを格納する
void
をテンプレート引数とするshared_ptr
に対してどんな型のポインタを代入したとしても、代入した型のデストラクタは、正しく実行される。通常、void*
に型変換して代入されたポインタは、delete
演算子を呼んだとしても元の型のデストラクタは呼び出されない。しかしshared_ptr
の場合は、代入されたポインタの型が持つデストラクタが正しく実行されることが保証される。保証の文面はデストラクタのページを参照。
#include <iostream>
#include <memory>
struct X {
~X()
{
std::cout << "X dtor" << std::endl;
}
};
struct Y {
~Y()
{
std::cout << "Y dtor" << std::endl;
}
};
int main()
{
std::shared_ptr<void> p(new X());
std::cout << 0 << std::endl;
p.reset(new Y()); // Xが破棄される
std::cout << 1 << std::endl;
} // Yが破棄される
xxxxxxxxxx
#include <iostream>
#include <memory>
struct X {
~X()
{
std::cout << "X dtor" << std::endl;
}
};
struct Y {
~Y()
{
std::cout << "Y dtor" << std::endl;
}
};
int main()
{
std::shared_ptr<void> p(new X());
std::cout << 0 << std::endl;
p.reset(new Y()); // Xが破棄される
std::cout << 1 << std::endl;
} // Yが破棄される
出力
0
X dtor
1
Y dtor
バージョン
言語
- C++11
処理系
- Clang: 3.0 ✅
- GCC: 4.3.6 ✅
- ICC: ??
- Visual C++: 2008 (TR1) ✅, 2010 ✅, 2012 ✅, 2013 ✅
関連項目
std::enable_shared_from_this
this
ポインタをshared_ptr
として使用する場合は、この機能を使用する
std::unique_ptr
- 所有権を共有する必要がない場合は、この機能を使用する