最終更新日時(UTC):
が更新

履歴 編集

class template
<memory>

std::shared_ptr

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_ptrconst修飾キャスト 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人になる。
  // 誰もリソースを参照しなくなったので、リソースが解放される。

出力

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が破棄される

出力

0
X dtor
1
Y dtor

バージョン

言語

  • C++11

処理系

関連項目

  • std::enable_shared_from_this
    • thisポインタをshared_ptrとして使用する場合は、この機能を使用する
  • std::unique_ptr
    • 所有権を共有する必要がない場合は、この機能を使用する

参照