SlideShare a Scribd company logo
1 of 84
Download to read offline
shared_ptr & weak_ptr
               くらいおらいと
        http://twitter.com/Cryolite/




1                                      2009/12/14
キーワードは所有 (ownership)
    • “…, so keeping track of an object’s
      ownership is hard work.”    – More Effective C++
    • “Observe the canonical exception-safety
      rules: Always use the “RAII” idiom to
      resource ownership and management.”
                                      – Exceptional C++
    • “Containers of raw pointers make manual
      ownership management tricky, so …”
                                   – Modern C++ Design




2                                               2009/12/14
所有とは…



    • 所有とは権利だ
      俺が所有しているものを勝⼿に捨てるな



    • 所有とは義務だ
      1回だけ,確実に,事後処理をしろ



3                        2009/12/14
所有を制するものが C++ を制する



    • 所有の権利を主張しないと…
      「俺がまだ使っているのに捨てられた!」
                => Dangling pointer

    • 所有の義務を果たしていないと…
      「誰も使ってないのに⽚付いていない!」
                => Memory leak


4                              2009/12/14
所有の種類と例
    • 所有者がただ⼀⼈, 所有者変更不可
      • 配列とその要素
      • クラスオブジェクトとメンバ変数
      • 関数スコープ (の実⾏) と⾃動変数
      • プログラム (の実⾏) と静的変数
    • 所有者がただ⼀⼈, 所有者変更可
      • std::auto_ptr
      • (ムーブセマンティクス)
    • 共有 – 所有者が複数
      • boost::shared_ptr

5                            2009/12/14
共有は難しい




6        2009/12/14
共有は難しい



    私が⽚付けましょう




7               2009/12/14
共有は難しい

                 いえいえ,ここは
    私が⽚付けましょう   私が⽚付けましょう




8                       2009/12/14
共有は難しい

                 いえいえ,ここは
    私が⽚付けましょう   私が⽚付けましょう




       え,ちょ,俺まだ使ってる
9                       2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

                        所有カウント

                 1




10                               2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

                        所有カウント

                 2




11                               2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

                        所有カウント

                 3




12                               2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

                        所有カウント

                 4




13                               2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

 所有カウントが0になったら          所有カウント
    片づけを実行
                 4




14                               2009/12/14
所有カウントは所有の権利を保障する

     所有の権利:
     誰かが所有していれば    共有されるもの
     勝手に片付けるな
            O.K.             所有カウント

                      1




15                                    2009/12/14
所有カウントは所有の義務を履行する
     所有カウントが0になれば
      後片付け処理を実行
                       共有されるもの

     所有の義務:                      所有カウント
     1度だけ, 確実に, 片付け
                          0
                O.K.




16                                        2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


              共有されるもの

                        所有カウント

                 4




17                               2009/12/14
shared_ptr – 共有を所有カウントで簡単・安全に扱う


                         共有されるもの

                                    所有カウント

                             4



     shared_ptr shared_ptr   shared_ptr   shared_ptr



18                                             2009/12/14
shared_ptr は所有(の義務と権利)とポインタだ
     • ポインタとして動作する shared_ptr
       C++ の生ポインタと同じように動作
     • 所有の権利を保障する shared_ptr
       ポインタとして指しているものは生きている
                強いポインタ
            所有しているものとポインタが
            指しているものを一致させる
     • 所有の義務を履行する shared_ptr
       所有カウントが0になったら関数オブジェクト
       (デリータ) を実行 delete だけじゃない
19                           2009/12/14
shared_ptr の基本
     {
         shared_ptr<int> p(new int(42));
         cout << *p << endl;
         shared_ptr<int> q = p;
         p.reset();
         cout << *q << endl;
     }




20                                         2009/12/14
shared_ptr の基本
     {
         shared_ptr<int> p(new int(42));
         cout << *p << endl;
         shared_ptr<int> q = p;
         p.reset();
         cout << *q << endl;
     }
                          ポインタとして動作
                               +
                        権利を保障 (参照外しが安全)

21                                         2009/12/14
shared_ptr の基本
     {
         shared_ptr<int> p(new int(42));
         cout << *p << endl;
         shared_ptr<int> q = p;
         p.reset();
         cout << *q << endl;
     }
                          ポインタとして動作
                               +
         義務を履行
                        権利を保障 (参照外しが安全)

22                                         2009/12/14
shared_ptr – int と同程度にスレッド安全


                         共有されるもの

                                    所有カウント
                                    カウントの変化は
                             4      同期保護




     shared_ptr shared_ptr   shared_ptr   shared_ptr



23                                             2009/12/14
所有カウントは循環所有を扱えない



              1

         所有
                  所有

              1

      所有カウントが永遠に非0

24                     2009/12/14
発表終わり




25      2009/12/14
shared_ptr の重要なデザインゴール



     • ポインタと同等の型互換性 / バイナリ互換性

     • 非侵入性 – あなたのクラス定義に変更なし


         所有の共有・受け渡しを表現する
         所有の共有・受け渡しを表現する
           標準インタフェイスの確立
           標準インタフェイスの確立


26                        2009/12/14
オレオレスマートポインタ
     void processX(shared_ptr<X> px);

     oreore_ptr<X> px(new X(…));
     processX(px); // コンパイルエラー




27                                      2009/12/14
オレオレスマートポインタ
     void processX(shared_ptr<X> px);

     template<class P> struct D {
        P p_;
        void operator()(void const *) { p_.reset(); }
     };

     oreore_ptr<X> px(new X(…));
     shared_ptr<X> qx(px.get(), D<oreore_ptr<X> >(px));
     processX(qx); // O.K.

28                                                      2009/12/14
オレオレスマートポインタ
     void processX(shared_ptr<X> px);

     template<class P> struct D {
                ポイント1
        P p_;
               shared_ptr の「所有」は型に現れない
        void operator()(void const *) { p_.reset(); }
     };
              ポイント2
     oreore_ptr<X> px(new X(…));
                    「所有」は型に現れない
     shared_ptr<X> qx(px.get(), =
                                D<oreore_ptr<X> >(px));
                コンストラクタで「所有」が決まる
     processX(qx);

29                                                 2009/12/14
所有しない
     void processX(shared_ptr<X> px);

     static X x; // 静的変数

     struct NullDeleter {
        void operator()(void *){}
     };

     shared_ptr<X> px(&x, NullDeleter());
     processX(px);

30                                          2009/12/14
所有しない
     void processX(shared_ptr<X> px);

     static X x; // 静的変数
           ポイント1

     Structshared_ptr の「所有」は型に現れない
              NullDeleter {
        void operator()(void *){}
     };      ポイント2
                   「所有」は型に現れない
                               =
     shared_ptr<X> px(&x, NullDeleter());
               コンストラクタで「所有」が決まる
     processX(px);

31                                      2009/12/14
バイナリ境界を越える – 生ポインタの場合
      a.exe (デバッグビルド)     b.dll (リリースビルド)
int main(){
  int *p = new int(42);
  f(p);                   void f(int *p){
  p = 0;                    .....
  .....                     .....
}                           delete p;
                          }

      異なるコンパイル設定の new と delete の
       組み合わせは環境によってはダウト
32                                          2009/12/14
バイナリ境界を越える – shared_ptr の場合
      a.exe (デバッグビルド)               b.dll (リリースビルド)
int main(){
  shared_ptr<int> p(new int(42));
  f(p);                             void f(shared_ptr<int> p){
  p.reset();                          .....
  .....                               .....
}                                     p.reset();
                                    }



33                                                     2009/12/14
バイナリ境界を越える – shared_ptr の場合
      a.exe (デバッグビルド)               b.dll (リリースビルド)
int main(){
  shared_ptr<int> p(new int(42));
  f(p);                             void f(shared_ptr<int> p){
  p.reset();                          .....
  .....                               .....
}                                     p.reset();
                                    }
             デバッグビルドの delete をここで設定

34                                                     2009/12/14
バイナリ境界を越える – shared_ptr の場合
      a.exe (デバッグビルド)               b.dll (リリースビルド)
int main(){
  shared_ptr<int> p(new int(42));
  f(p);                             void f(shared_ptr<int> p){
  p.reset();                          .....
  .....                               .....
}                                     p.reset();
                                    }
             デバッグビルドの delete をここで設定
            デバッグビルドの delete が呼び出される
35                                                     2009/12/14
バイナリ境界を越える – shared_ptr の場合
      a.exe (デバッグビルド)               b.dll (リリースビルド)
int main(){
  shared_ptr<int> p(new int(42));
  f(p);                           void f(shared_ptr<int> p){
  p.reset();                        .....
  .....                             .....
}               どの delete が設定されていようがp.reset();
                      バイナリ互換性を維持  }
            デバッグビルドの delete をここで設定
           デバッグビルドの delete が呼び出される
36                                                   2009/12/14
所有だけの shared_ptr
     shared_ptr<int> p(new int(42)); // (A)

     shared_ptr<void> q = p;
     p.reset();
     // 以下, (A) で生成した int は q が所有




37                                            2009/12/14
shared_ptr<void> による遅延解放
     // HeavyToDispose は削除のコスト大
     shared_ptr<HeavyToDispose> px(…);
     …
     // ここで削除して処理が止まると困る…
     px.reset();




38                                       2009/12/14
shared_ptr<void> による遅延解放
     vector<shared_ptr<void> > to_be_disposed;

     shared_ptr<HeavyToDispose1> px(…);
     shared_ptr<HeavyToDispose2> py(…);
     …
     // ここで削除して処理が止まると困る…
     to_be_disposed.push_back(px); px.reset();
     to_be_disposed.push_back(py); py.reset();
     …
     // 適当なタイミング or 別スレッドで
     // to_be_disposed.clear() を実行
39                                               2009/12/14
weak_ptr

                                  共有されるもの


                  所有カウント
                                             弱いカウント
                                      4, 2


                                                weak_ptr
     shared_ptr          shared_ptr      weak_ptr
            shared_ptr          shared_ptr

40                                                  2009/12/14
weak_ptr

                                  共有されるもの


                  所有カウント
                                             弱いカウント
                                      0, 2


                                                weak_ptr
     shared_ptr          shared_ptr      weak_ptr
            shared_ptr          shared_ptr

41                                                  2009/12/14
weak_ptr
 所有カウントが0になったら
                    共有されるもの
    片づけを実行

           所有カウント
                              弱いカウント
                      0, 2


                               weak_ptr
                        weak_ptr


42                                 2009/12/14
weak_ptr




           所有カウント
                           弱いカウント
                    0, 2


                             weak_ptr
                      weak_ptr


43                               2009/12/14
weak_ptr




           所有カウント
                           弱いカウント
                    0, 0


                             weak_ptr
                      weak_ptr


44                               2009/12/14
weak_ptr




                      0, 0
      弱いカウントが0になったら
     カウントオブジェクトを片付け
                               weak_ptr
                        weak_ptr


45                                 2009/12/14
weak_ptr にできること – その1

                                  共有されるもの


                  所有カウント
                                               弱いカウント
                                      4, 2

         「所有カウントが0かどうか?」に答える
                                                weak_ptr
     shared_ptr          shared_ptr      weak_ptr
            shared_ptr          shared_ptr

46                weak_ptr::expired == false        2009/12/14
weak_ptr にできること – その1




          所有カウント
                                     弱いカウント
                            0, 2

     「所有カウントが0かどうか?」に答える
                        weak_ptr
                               weak_ptr


47       weak_ptr::expired == true        2009/12/14
weak_ptr にできること – その1




           所有カウント
                              弱いカウント
                       0, 2

      「所有カウントが0かどうか?」に答える
               =            weak_ptr
     「対象が死んでいるかどうか?」に答える
                     weak_ptr


48                               2009/12/14
weak_ptr にできること – その2

                   共有されるもの


          所有カウント
                               弱いカウント
                     1, 2

      shared_ptr
                                   weak_ptr
                        weak_ptr
       対象が生きていたら,それを
      所有する shared_ptr を作り出せる
49                                     2009/12/14
weak_ptr にできること – その2

                         共有されるもの


          所有カウント
                                   弱いカウント
                           2, 2

      shared_ptr
                                      weak_ptr
            shared_ptr     weak_ptr
       対象が生きていたら,それを
      所有する shared_ptr を作り出せる
50                                        2009/12/14
weak_ptr にできること – その2




         所有カウント
                               弱いカウント
                    0, 2


                                   weak_ptr
                        weak_ptr
 対象が死んでいたら空の shared_ptr しか取り出せない
51                                     2009/12/14
weak_ptr にできること – その2




         所有カウント
                               弱いカウント
                       0, 2


                                   weak_ptr
          shared_ptr    weak_ptr
 対象が死んでいたら空の shared_ptr しか取り出せない
52                                     2009/12/14
weak_ptr にできることのまとめ

     • 「対象が生きているかどうか?」を答えるプロ
       クシ

     • 対象が生きていたら shared_ptr に格上げ可
       能




53                            2009/12/14
weak_ptr の基本
     shared_ptr<int> p(new int(42)); // (A)
     weak_ptr<int> wp = p;
     cout << wp.expired() << endl; // => “false”
     shared_ptr<int> q = wp.lock();
     cout << *q << endl; // => “42”, q も所有
     p.reset(); q.reset(); // (A) の int を解放
     cout << wp.expired() << endl; // => “true”
     shared_ptr<int> r = wp.lock();
     assert(r == 0);


54                                             2009/12/14
生ポインタから shared_ptr を取得したい
     void Framework::onEvent(X *p)
     {
       // *p を所有する shared_ptr を取りたい
     }




55                                    2009/12/14
this への shared_ptr
      struct X {
         shared_ptr<X> this_; // this への shared_ptr
         shared_ptr<X> getShared(){ return this_; }
      };

      void Framework::onEvent(X *p)
      {
        shared_ptr<X> px = p->getShared();
      }


56                                             2009/12/14
this への shared_ptr はダメ
     struct X {
        shared_ptr<X> this_; // this への shared_ptr
        shared_ptr<X> getShared(){ return this_; }
     };

     void Framework::onEvent(X *p)
     {
       shared_ptr<X> px = p->getShared();
     }


57                                            2009/12/14
this への shared_ptr はダメ
     struct X {
        Q. なぜダメか?
        shared_ptr<X> this_; // this への shared_ptr
        shared_ptr<X> getShared(){ return this_; }
                             X
     };
        クラスオブジェクトは
                                     所有
          メンバ変数を所有
     void Framework::onEvent(X *p)
     {
                   X::shared_ptr this_
        shared_ptr<X> px = p->getShared();
     }
        A. 所有が循環しているのでダメ


58                                            2009/12/14
weak_ptr の使い方 – this への weak_ptr
     struct X {
        weak_ptr<X> this_; // this への weak_ptr
        shared_ptr<X> getShared(){ return this_; }
     };

     void Framework::onEvent(X *p)
     {
       shared_ptr<X> px = p->getShared();
     }


59                                               2009/12/14
weak_ptr の使い方 – this への weak_ptr
     struct X {
        weak_ptr<X> this_; // this への weak_ptr
        shared_ptr<X> getShared(){ return this_; }
     };

     void Framework::onEvent(X *p)
     {
       shared_ptr<X> px = p->getShared();
     }

     参考: boost::enable_shared_from_this
60                                               2009/12/14
Observer (Publisher/Subscriber)




61                                2009/12/14
Observer でよくある事故




62                 2009/12/14
Observer でよくある事故




       死んだオブジェクトにアクセス
63                      2009/12/14
安全な Observer




     • 死んだオブジェクトにイベントを通知しない
     • イベント通知中に subscriber を解放させない
64                               2009/12/14
安全な Observer




void Publisher::subscribe(function<void ()> call_back,
                          weak_ptr<void> wp);

shared_ptr<Subscriber1> p…
Publisher::subscribe(
 bind(&Subscriber1::notifyEvent, p.get()), p);
65                                                  2009/12/14
安全な Observer




weak_ptr<void> wp…; // subscriber への weak_ptr
if (shared_ptr<void> p = wp.lock()) {
   // 生きているときだけ通知 + call_back 中だけ所有
   call_back();
}
66                                           2009/12/14
安全な Observer




     …ということが Boost.Signal2 で出来ます
     鍵は weak_ptr<void> & shared_ptr<void>
67                                          2009/12/14
オブジェクト間グローバルマッピング
 share_ptr

             a
 share_ptr   b
             c




 share_ptr   share_ptr

68                       2009/12/14
オブジェクト間グローバルマッピング
 share_ptr    map<void *, Y> g_map; // グローバル

             a                        y1
 share_ptr   b                        y2

             c                        y3




 share_ptr   share_ptr

69                                         2009/12/14
オブジェクト間グローバルマッピング
 share_ptr    map<void *, Y> g_map; // グローバル

             a                        y1
 share_ptr   b                        y2

             c                        y3


     c が消えると…

 share_ptr   share_ptr

70                                         2009/12/14
オブジェクト間グローバルマッピング
 share_ptr    map<void *, Y> g_map; // グローバル

             a                        y1
 share_ptr   b                        y2

             c                        y3


     c が消えると…            無駄なマップエントリ
                         (デッドマップ) が発生
 share_ptr   share_ptr

71                                         2009/12/14
策1. キーを weak_ptr にして適度にクリーンアップ
 share_ptr       map<weak_ptr<void>, Y> g_map;

             a                            y1
 share_ptr   b                            y2

             c                            y3




72                                               2009/12/14
策1. キーを weak_ptr にして適度にクリーンアップ
 share_ptr         map<weak_ptr<void>, Y> g_map;

               a                                  y1
 share_ptr     b                                  y2

               c                                  y3

     // 以下を適度に実行
     for (auto i = g_map.begin(); i != g_map.end();) {
       if (i->first.expired()) g_map.erase(i++);
       else ++i;
     }
73                                                       2009/12/14
策1. キーを weak_ptr にして適度にクリーンアップ
 share_ptr       map<weak_ptr<void>, Y> g_map;

             a                            y1
 share_ptr   b                            y2

             c                            y3


                 デッドマップが適度に解消される



74                                               2009/12/14
策2. マップエントリも所有する
 share_ptr               map<void *, Y>

             a                            y1
 share_ptr   b                            y2

             c                            y3




 share_ptr   share_ptr

75                                             2009/12/14
策2. マップエントリも所有する
 share_ptr                     map<void *, Y>

                 a
           struct D{                                 y1
              map<void *, Y> &m_;
 share_ptr       b                                   y2
              void operator()(void *p){
                m_.erase(p); delete p;
                 c                                   y3
              }
           };

          D d(g_map);
          shared_ptr<C> pc(new C(), D(g_map));
 share_ptrg_map.insert(make_pair(pc.get(), Y(…)));
              share_ptr

76                                                        2009/12/14
策2. マップエントリも所有する
 share_ptr               map<void *, Y>

             a                            y1
 share_ptr   b                            y2

             c                            y3


 c を所有する shared_ptr がなくなると…

 share_ptr   share_ptr

77                                             2009/12/14
策2. マップエントリも所有する
 share_ptr               map<void *, Y>

             a                            y1
 share_ptr   b                            y2

             c                            y3
                 c をキーとするエントリも自動で erase

 c を所有する shared_ptr がなくなると…

 share_ptr   share_ptr

78                                             2009/12/14
循環所有を何とかする
     // こういうことがしたい
     shared_ptr<X> px = …;
     shared_ptr<Y> py = …;

     pyy = px->getSharedY(); // X が Y を所有?
     assert(pyy == py);

     pxx = py->getSharedX(); // Y が X を所有?
     assert(pxx == px);

79                                     2009/12/14
循環所有を何とかする
     // こういうことがしたい
     shared_ptr<X> px = …;
     shared_ptr<Y> py = …;

                        所有
     pyy = px->getSharedY(); // X が Y を所有?
     assert(pyy == py);
                   X     ?       Y

     pxx = py->getSharedX(); // Y が X を所有?
                        所有
     assert(pxx == px);

80                                     2009/12/14
循環所有を何とかする
     // こういうことがしたい
     shared_ptr<X> px = …;
     shared_ptr<Y> py = …;
                    shared_ptr
                   所有        所有
     pyy = px->getSharedY(); // X が Y を所有?
     assert(pyy == py);
                   X             Y

     pxx = py->getSharedX(); // Y が X を所有?
     assert(pxx == px);

81                                     2009/12/14
循環所有を何とかする
     // こういうことがしたい
     shared_ptr<X> px = …;
     shared_ptr<Y> py = …;
                     shared_ptr
           ポイント
                   所有         所有
     pyy = px->getSharedY(); // X が Y を所有?
     assert(pyy == py);
                   X             Y

     pxx = py->getSharedX(); // Y が X を所有?
                   shared_ptr<X>
     assert(pxx == px);

82                                     2009/12/14
循環所有を何とかする
     // こういうことがしたい
     shared_ptr<X> px = …;
     shared_ptr<Y> py = …;
                    shared_ptr   ポイント

                   所有        所有
     pyy = px->getSharedY(); // X が Y を所有?
     assert(pyy == py);
                   X             Y

     pxx = py->getSharedX(); // Y が X を所有?
                   shared_ptr<Y>
     assert(pxx == px);

83                                      2009/12/14
まとめ
      • C++ では所有が重要
      • shared_ptr は所有者が複数居る場合に
        – 所有カウントで簡単・安全に動作
        – 動的デリータによる高い互換性を維持
      • weak_ptr
        – 「生きているかどうか」を答えるプロキシ
        – shared_ptr に格上げして一時的に所有
      • shared_ptr / weak_ptr で楽しい C++ ライフ



84                                      2009/12/14

More Related Content

Recently uploaded

Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 

Recently uploaded (10)

Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

shared_ptr & weak_ptr (pdf 第2版)

  • 1. shared_ptr & weak_ptr くらいおらいと http://twitter.com/Cryolite/ 1 2009/12/14
  • 2. キーワードは所有 (ownership) • “…, so keeping track of an object’s ownership is hard work.” – More Effective C++ • “Observe the canonical exception-safety rules: Always use the “RAII” idiom to resource ownership and management.” – Exceptional C++ • “Containers of raw pointers make manual ownership management tricky, so …” – Modern C++ Design 2 2009/12/14
  • 3. 所有とは… • 所有とは権利だ 俺が所有しているものを勝⼿に捨てるな • 所有とは義務だ 1回だけ,確実に,事後処理をしろ 3 2009/12/14
  • 4. 所有を制するものが C++ を制する • 所有の権利を主張しないと… 「俺がまだ使っているのに捨てられた!」 => Dangling pointer • 所有の義務を果たしていないと… 「誰も使ってないのに⽚付いていない!」 => Memory leak 4 2009/12/14
  • 5. 所有の種類と例 • 所有者がただ⼀⼈, 所有者変更不可 • 配列とその要素 • クラスオブジェクトとメンバ変数 • 関数スコープ (の実⾏) と⾃動変数 • プログラム (の実⾏) と静的変数 • 所有者がただ⼀⼈, 所有者変更可 • std::auto_ptr • (ムーブセマンティクス) • 共有 – 所有者が複数 • boost::shared_ptr 5 2009/12/14
  • 6. 共有は難しい 6 2009/12/14
  • 7. 共有は難しい 私が⽚付けましょう 7 2009/12/14
  • 8. 共有は難しい いえいえ,ここは 私が⽚付けましょう 私が⽚付けましょう 8 2009/12/14
  • 9. 共有は難しい いえいえ,ここは 私が⽚付けましょう 私が⽚付けましょう え,ちょ,俺まだ使ってる 9 2009/12/14
  • 10. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 1 10 2009/12/14
  • 11. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 2 11 2009/12/14
  • 12. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 3 12 2009/12/14
  • 13. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 4 13 2009/12/14
  • 14. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウントが0になったら 所有カウント 片づけを実行 4 14 2009/12/14
  • 15. 所有カウントは所有の権利を保障する 所有の権利: 誰かが所有していれば 共有されるもの 勝手に片付けるな O.K. 所有カウント 1 15 2009/12/14
  • 16. 所有カウントは所有の義務を履行する 所有カウントが0になれば 後片付け処理を実行 共有されるもの 所有の義務: 所有カウント 1度だけ, 確実に, 片付け 0 O.K. 16 2009/12/14
  • 17. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 4 17 2009/12/14
  • 18. shared_ptr – 共有を所有カウントで簡単・安全に扱う 共有されるもの 所有カウント 4 shared_ptr shared_ptr shared_ptr shared_ptr 18 2009/12/14
  • 19. shared_ptr は所有(の義務と権利)とポインタだ • ポインタとして動作する shared_ptr C++ の生ポインタと同じように動作 • 所有の権利を保障する shared_ptr ポインタとして指しているものは生きている 強いポインタ 所有しているものとポインタが 指しているものを一致させる • 所有の義務を履行する shared_ptr 所有カウントが0になったら関数オブジェクト (デリータ) を実行 delete だけじゃない 19 2009/12/14
  • 20. shared_ptr の基本 { shared_ptr<int> p(new int(42)); cout << *p << endl; shared_ptr<int> q = p; p.reset(); cout << *q << endl; } 20 2009/12/14
  • 21. shared_ptr の基本 { shared_ptr<int> p(new int(42)); cout << *p << endl; shared_ptr<int> q = p; p.reset(); cout << *q << endl; } ポインタとして動作 + 権利を保障 (参照外しが安全) 21 2009/12/14
  • 22. shared_ptr の基本 { shared_ptr<int> p(new int(42)); cout << *p << endl; shared_ptr<int> q = p; p.reset(); cout << *q << endl; } ポインタとして動作 + 義務を履行 権利を保障 (参照外しが安全) 22 2009/12/14
  • 23. shared_ptr – int と同程度にスレッド安全 共有されるもの 所有カウント カウントの変化は 4 同期保護 shared_ptr shared_ptr shared_ptr shared_ptr 23 2009/12/14
  • 24. 所有カウントは循環所有を扱えない 1 所有 所有 1 所有カウントが永遠に非0 24 2009/12/14
  • 25. 発表終わり 25 2009/12/14
  • 26. shared_ptr の重要なデザインゴール • ポインタと同等の型互換性 / バイナリ互換性 • 非侵入性 – あなたのクラス定義に変更なし 所有の共有・受け渡しを表現する 所有の共有・受け渡しを表現する 標準インタフェイスの確立 標準インタフェイスの確立 26 2009/12/14
  • 27. オレオレスマートポインタ void processX(shared_ptr<X> px); oreore_ptr<X> px(new X(…)); processX(px); // コンパイルエラー 27 2009/12/14
  • 28. オレオレスマートポインタ void processX(shared_ptr<X> px); template<class P> struct D { P p_; void operator()(void const *) { p_.reset(); } }; oreore_ptr<X> px(new X(…)); shared_ptr<X> qx(px.get(), D<oreore_ptr<X> >(px)); processX(qx); // O.K. 28 2009/12/14
  • 29. オレオレスマートポインタ void processX(shared_ptr<X> px); template<class P> struct D { ポイント1 P p_; shared_ptr の「所有」は型に現れない void operator()(void const *) { p_.reset(); } }; ポイント2 oreore_ptr<X> px(new X(…)); 「所有」は型に現れない shared_ptr<X> qx(px.get(), = D<oreore_ptr<X> >(px)); コンストラクタで「所有」が決まる processX(qx); 29 2009/12/14
  • 30. 所有しない void processX(shared_ptr<X> px); static X x; // 静的変数 struct NullDeleter { void operator()(void *){} }; shared_ptr<X> px(&x, NullDeleter()); processX(px); 30 2009/12/14
  • 31. 所有しない void processX(shared_ptr<X> px); static X x; // 静的変数 ポイント1 Structshared_ptr の「所有」は型に現れない NullDeleter { void operator()(void *){} }; ポイント2 「所有」は型に現れない = shared_ptr<X> px(&x, NullDeleter()); コンストラクタで「所有」が決まる processX(px); 31 2009/12/14
  • 32. バイナリ境界を越える – 生ポインタの場合 a.exe (デバッグビルド) b.dll (リリースビルド) int main(){ int *p = new int(42); f(p); void f(int *p){ p = 0; ..... ..... ..... } delete p; } 異なるコンパイル設定の new と delete の 組み合わせは環境によってはダウト 32 2009/12/14
  • 33. バイナリ境界を越える – shared_ptr の場合 a.exe (デバッグビルド) b.dll (リリースビルド) int main(){ shared_ptr<int> p(new int(42)); f(p); void f(shared_ptr<int> p){ p.reset(); ..... ..... ..... } p.reset(); } 33 2009/12/14
  • 34. バイナリ境界を越える – shared_ptr の場合 a.exe (デバッグビルド) b.dll (リリースビルド) int main(){ shared_ptr<int> p(new int(42)); f(p); void f(shared_ptr<int> p){ p.reset(); ..... ..... ..... } p.reset(); } デバッグビルドの delete をここで設定 34 2009/12/14
  • 35. バイナリ境界を越える – shared_ptr の場合 a.exe (デバッグビルド) b.dll (リリースビルド) int main(){ shared_ptr<int> p(new int(42)); f(p); void f(shared_ptr<int> p){ p.reset(); ..... ..... ..... } p.reset(); } デバッグビルドの delete をここで設定 デバッグビルドの delete が呼び出される 35 2009/12/14
  • 36. バイナリ境界を越える – shared_ptr の場合 a.exe (デバッグビルド) b.dll (リリースビルド) int main(){ shared_ptr<int> p(new int(42)); f(p); void f(shared_ptr<int> p){ p.reset(); ..... ..... ..... } どの delete が設定されていようがp.reset(); バイナリ互換性を維持 } デバッグビルドの delete をここで設定 デバッグビルドの delete が呼び出される 36 2009/12/14
  • 37. 所有だけの shared_ptr shared_ptr<int> p(new int(42)); // (A) shared_ptr<void> q = p; p.reset(); // 以下, (A) で生成した int は q が所有 37 2009/12/14
  • 38. shared_ptr<void> による遅延解放 // HeavyToDispose は削除のコスト大 shared_ptr<HeavyToDispose> px(…); … // ここで削除して処理が止まると困る… px.reset(); 38 2009/12/14
  • 39. shared_ptr<void> による遅延解放 vector<shared_ptr<void> > to_be_disposed; shared_ptr<HeavyToDispose1> px(…); shared_ptr<HeavyToDispose2> py(…); … // ここで削除して処理が止まると困る… to_be_disposed.push_back(px); px.reset(); to_be_disposed.push_back(py); py.reset(); … // 適当なタイミング or 別スレッドで // to_be_disposed.clear() を実行 39 2009/12/14
  • 40. weak_ptr 共有されるもの 所有カウント 弱いカウント 4, 2 weak_ptr shared_ptr shared_ptr weak_ptr shared_ptr shared_ptr 40 2009/12/14
  • 41. weak_ptr 共有されるもの 所有カウント 弱いカウント 0, 2 weak_ptr shared_ptr shared_ptr weak_ptr shared_ptr shared_ptr 41 2009/12/14
  • 42. weak_ptr 所有カウントが0になったら 共有されるもの 片づけを実行 所有カウント 弱いカウント 0, 2 weak_ptr weak_ptr 42 2009/12/14
  • 43. weak_ptr 所有カウント 弱いカウント 0, 2 weak_ptr weak_ptr 43 2009/12/14
  • 44. weak_ptr 所有カウント 弱いカウント 0, 0 weak_ptr weak_ptr 44 2009/12/14
  • 45. weak_ptr 0, 0 弱いカウントが0になったら カウントオブジェクトを片付け weak_ptr weak_ptr 45 2009/12/14
  • 46. weak_ptr にできること – その1 共有されるもの 所有カウント 弱いカウント 4, 2 「所有カウントが0かどうか?」に答える weak_ptr shared_ptr shared_ptr weak_ptr shared_ptr shared_ptr 46 weak_ptr::expired == false 2009/12/14
  • 47. weak_ptr にできること – その1 所有カウント 弱いカウント 0, 2 「所有カウントが0かどうか?」に答える weak_ptr weak_ptr 47 weak_ptr::expired == true 2009/12/14
  • 48. weak_ptr にできること – その1 所有カウント 弱いカウント 0, 2 「所有カウントが0かどうか?」に答える = weak_ptr 「対象が死んでいるかどうか?」に答える weak_ptr 48 2009/12/14
  • 49. weak_ptr にできること – その2 共有されるもの 所有カウント 弱いカウント 1, 2 shared_ptr weak_ptr weak_ptr 対象が生きていたら,それを 所有する shared_ptr を作り出せる 49 2009/12/14
  • 50. weak_ptr にできること – その2 共有されるもの 所有カウント 弱いカウント 2, 2 shared_ptr weak_ptr shared_ptr weak_ptr 対象が生きていたら,それを 所有する shared_ptr を作り出せる 50 2009/12/14
  • 51. weak_ptr にできること – その2 所有カウント 弱いカウント 0, 2 weak_ptr weak_ptr 対象が死んでいたら空の shared_ptr しか取り出せない 51 2009/12/14
  • 52. weak_ptr にできること – その2 所有カウント 弱いカウント 0, 2 weak_ptr shared_ptr weak_ptr 対象が死んでいたら空の shared_ptr しか取り出せない 52 2009/12/14
  • 53. weak_ptr にできることのまとめ • 「対象が生きているかどうか?」を答えるプロ クシ • 対象が生きていたら shared_ptr に格上げ可 能 53 2009/12/14
  • 54. weak_ptr の基本 shared_ptr<int> p(new int(42)); // (A) weak_ptr<int> wp = p; cout << wp.expired() << endl; // => “false” shared_ptr<int> q = wp.lock(); cout << *q << endl; // => “42”, q も所有 p.reset(); q.reset(); // (A) の int を解放 cout << wp.expired() << endl; // => “true” shared_ptr<int> r = wp.lock(); assert(r == 0); 54 2009/12/14
  • 55. 生ポインタから shared_ptr を取得したい void Framework::onEvent(X *p) { // *p を所有する shared_ptr を取りたい } 55 2009/12/14
  • 56. this への shared_ptr struct X { shared_ptr<X> this_; // this への shared_ptr shared_ptr<X> getShared(){ return this_; } }; void Framework::onEvent(X *p) { shared_ptr<X> px = p->getShared(); } 56 2009/12/14
  • 57. this への shared_ptr はダメ struct X { shared_ptr<X> this_; // this への shared_ptr shared_ptr<X> getShared(){ return this_; } }; void Framework::onEvent(X *p) { shared_ptr<X> px = p->getShared(); } 57 2009/12/14
  • 58. this への shared_ptr はダメ struct X { Q. なぜダメか? shared_ptr<X> this_; // this への shared_ptr shared_ptr<X> getShared(){ return this_; } X }; クラスオブジェクトは 所有 メンバ変数を所有 void Framework::onEvent(X *p) { X::shared_ptr this_ shared_ptr<X> px = p->getShared(); } A. 所有が循環しているのでダメ 58 2009/12/14
  • 59. weak_ptr の使い方 – this への weak_ptr struct X { weak_ptr<X> this_; // this への weak_ptr shared_ptr<X> getShared(){ return this_; } }; void Framework::onEvent(X *p) { shared_ptr<X> px = p->getShared(); } 59 2009/12/14
  • 60. weak_ptr の使い方 – this への weak_ptr struct X { weak_ptr<X> this_; // this への weak_ptr shared_ptr<X> getShared(){ return this_; } }; void Framework::onEvent(X *p) { shared_ptr<X> px = p->getShared(); } 参考: boost::enable_shared_from_this 60 2009/12/14
  • 63. Observer でよくある事故 死んだオブジェクトにアクセス 63 2009/12/14
  • 64. 安全な Observer • 死んだオブジェクトにイベントを通知しない • イベント通知中に subscriber を解放させない 64 2009/12/14
  • 65. 安全な Observer void Publisher::subscribe(function<void ()> call_back, weak_ptr<void> wp); shared_ptr<Subscriber1> p… Publisher::subscribe( bind(&Subscriber1::notifyEvent, p.get()), p); 65 2009/12/14
  • 66. 安全な Observer weak_ptr<void> wp…; // subscriber への weak_ptr if (shared_ptr<void> p = wp.lock()) { // 生きているときだけ通知 + call_back 中だけ所有 call_back(); } 66 2009/12/14
  • 67. 安全な Observer …ということが Boost.Signal2 で出来ます 鍵は weak_ptr<void> & shared_ptr<void> 67 2009/12/14
  • 68. オブジェクト間グローバルマッピング share_ptr a share_ptr b c share_ptr share_ptr 68 2009/12/14
  • 69. オブジェクト間グローバルマッピング share_ptr map<void *, Y> g_map; // グローバル a y1 share_ptr b y2 c y3 share_ptr share_ptr 69 2009/12/14
  • 70. オブジェクト間グローバルマッピング share_ptr map<void *, Y> g_map; // グローバル a y1 share_ptr b y2 c y3 c が消えると… share_ptr share_ptr 70 2009/12/14
  • 71. オブジェクト間グローバルマッピング share_ptr map<void *, Y> g_map; // グローバル a y1 share_ptr b y2 c y3 c が消えると… 無駄なマップエントリ (デッドマップ) が発生 share_ptr share_ptr 71 2009/12/14
  • 72. 策1. キーを weak_ptr にして適度にクリーンアップ share_ptr map<weak_ptr<void>, Y> g_map; a y1 share_ptr b y2 c y3 72 2009/12/14
  • 73. 策1. キーを weak_ptr にして適度にクリーンアップ share_ptr map<weak_ptr<void>, Y> g_map; a y1 share_ptr b y2 c y3 // 以下を適度に実行 for (auto i = g_map.begin(); i != g_map.end();) { if (i->first.expired()) g_map.erase(i++); else ++i; } 73 2009/12/14
  • 74. 策1. キーを weak_ptr にして適度にクリーンアップ share_ptr map<weak_ptr<void>, Y> g_map; a y1 share_ptr b y2 c y3 デッドマップが適度に解消される 74 2009/12/14
  • 75. 策2. マップエントリも所有する share_ptr map<void *, Y> a y1 share_ptr b y2 c y3 share_ptr share_ptr 75 2009/12/14
  • 76. 策2. マップエントリも所有する share_ptr map<void *, Y> a struct D{ y1 map<void *, Y> &m_; share_ptr b y2 void operator()(void *p){ m_.erase(p); delete p; c y3 } }; D d(g_map); shared_ptr<C> pc(new C(), D(g_map)); share_ptrg_map.insert(make_pair(pc.get(), Y(…))); share_ptr 76 2009/12/14
  • 77. 策2. マップエントリも所有する share_ptr map<void *, Y> a y1 share_ptr b y2 c y3 c を所有する shared_ptr がなくなると… share_ptr share_ptr 77 2009/12/14
  • 78. 策2. マップエントリも所有する share_ptr map<void *, Y> a y1 share_ptr b y2 c y3 c をキーとするエントリも自動で erase c を所有する shared_ptr がなくなると… share_ptr share_ptr 78 2009/12/14
  • 79. 循環所有を何とかする // こういうことがしたい shared_ptr<X> px = …; shared_ptr<Y> py = …; pyy = px->getSharedY(); // X が Y を所有? assert(pyy == py); pxx = py->getSharedX(); // Y が X を所有? assert(pxx == px); 79 2009/12/14
  • 80. 循環所有を何とかする // こういうことがしたい shared_ptr<X> px = …; shared_ptr<Y> py = …; 所有 pyy = px->getSharedY(); // X が Y を所有? assert(pyy == py); X ? Y pxx = py->getSharedX(); // Y が X を所有? 所有 assert(pxx == px); 80 2009/12/14
  • 81. 循環所有を何とかする // こういうことがしたい shared_ptr<X> px = …; shared_ptr<Y> py = …; shared_ptr 所有 所有 pyy = px->getSharedY(); // X が Y を所有? assert(pyy == py); X Y pxx = py->getSharedX(); // Y が X を所有? assert(pxx == px); 81 2009/12/14
  • 82. 循環所有を何とかする // こういうことがしたい shared_ptr<X> px = …; shared_ptr<Y> py = …; shared_ptr ポイント 所有 所有 pyy = px->getSharedY(); // X が Y を所有? assert(pyy == py); X Y pxx = py->getSharedX(); // Y が X を所有? shared_ptr<X> assert(pxx == px); 82 2009/12/14
  • 83. 循環所有を何とかする // こういうことがしたい shared_ptr<X> px = …; shared_ptr<Y> py = …; shared_ptr ポイント 所有 所有 pyy = px->getSharedY(); // X が Y を所有? assert(pyy == py); X Y pxx = py->getSharedX(); // Y が X を所有? shared_ptr<Y> assert(pxx == px); 83 2009/12/14
  • 84. まとめ • C++ では所有が重要 • shared_ptr は所有者が複数居る場合に – 所有カウントで簡単・安全に動作 – 動的デリータによる高い互換性を維持 • weak_ptr – 「生きているかどうか」を答えるプロキシ – shared_ptr に格上げして一時的に所有 • shared_ptr / weak_ptr で楽しい C++ ライフ 84 2009/12/14