2012-04-11 7 views
2

ベクター内にポインタを保持し、dtor内のメモリーを解放できるようにしている状況です。ノーティファイヤ/シグナルがスコープ外に出たときに、ブースト・バインドでコールバック・リスナー・オブジェクトを割り振り解除する

ブースト信号からのコールバック(スロット)をリッスンするオブジェクトがあります。これらのオブジェクトは、作成されているメソッドよりもスコープが大きく、ブースト信号を聞く必要があります。メモリをヒープに割り当てる必要があり、即座にそのインスタンスを使用して信号をブーストすることに加入しました。クラスが信号を保持したときに今、これらのオブジェクトはメモリから割り当てを解除する必要があります

  • は、ブースト信号がスコープとすべてのリスニングの外に出たとき、すべてのこれらのオブジェクトの割り当てを解除後押しんが、私のオプションが何であるかdestroyed.Nowありますboost:バインドされたオブジェクトは破棄されますか?

  • これで共有ポインタまたはスマートポインタは役に立ちますか?

  • シグナリングサービスでこれらのポインタのベクトルを持って、デストラクタで割り当てを解除する必要がありますか?もっと良い方法はありますか?

    void methodA(){ 
    
    CallbackHandler* cbHandler=new CallbackHandler(..); //Allocating in heap as we want to receive boost signals on 
                     //this instance even after this method exits 
    signalingService.subscribeToCertainSignals(signalType,boost::bind(&CallbackHandler::boostSlotListener,cbHandler,_1)); 
    } 
    
    
    // Boost Signal -SignalingService 
    boost::signal<void (const std::string &msg)> signal1; 
    boost::signal<void (const std::string &msg)> signal2; 
    
    void subscribeToCertainSignals(const std::string& signalType,boost::function<void (const std::string& str)> bindObject){ 
         this->signal1.connect(bindObject); 
         this->signal2.connect(bindObject); 
    
    } 
    void sendSignals(A a){ 
        if(check){ 
         this->signal1("somestring1"); 
         }else{ 
         this->signal1("somestring1"); 
         } 
    

    };あなたがこれを行うことができます

+0

私はC++プログラミングを開始するJava開発者です。いくつかの良いC++の本を読んだが、やはり自分の道を見つけようとした。基本的に何かが間違っている場合は助言をしてください。 – Yeshvanthni

答えて

1

一つの方法は、外部のリスナーに信号を保持しているオブジェクトのすべてのリスナーにshared_ptr秒を格納し、weak_ptrのことであろう。信号を保持するオブジェクトが破壊されると、shared_ptrのそれぞれの参照カウントは0になり、指しているリスナーが削除されます。次に、weak_ptrが信号を保持するオブジェクトの外側からリスナーにアクセスしようとすると、ポインターが削除されるため、ロックが失敗します。これは、lockがnullを返すので検出しやすくなります。shared_ptr

は、ここで(ちょうどポイントを説明するために、残念ながらBoost.Signalsを使用していない)あなたのための具体的な例です:

#include <iostream> 
#include <memory> 
#include <vector> 

class Listener 
{ 
public: 
    virtual ~Listener() {} 
    virtual void signal() = 0; 
}; 

class Subject 
{ 
private: 
    std::vector<std::shared_ptr<Listener> > m_listeners; 
public: 
    void add_listener(const std::shared_ptr<Listener>& listener) 
    { 
     m_listeners.push_back(listener); 
    } 

    void signal_all() 
    { 
     // Note that you could use "auto it = ..." here in C++11. 
     for(std::vector<std::shared_ptr<Listener> >::iterator it=m_listeners.begin(), iend=m_listeners.end(); it!=iend; ++it) 
     { 
      (*it)->signal(); 
     } 
    } 
}; 

class MyListener : public Listener 
{ 
    void signal() 
    { 
     std::cout << "Signalled!\n"; 
    } 
}; 

int main() 
{ 
    std::vector<std::weak_ptr<Listener> > listeners; 

    { 
     Subject s; 

     std::shared_ptr<Listener> listener(new MyListener); 
     s.add_listener(listener); 
     listeners.push_back(listener); 
     listener.reset(); 

     s.signal_all(); 

     // Locking the listener yields the listener here. 
     std::cout << listeners[0].lock() << '\n'; 
    } 

    // Locking the listener now yields null because s no longer exists. 
    std::cout << listeners[0].lock() << '\n'; 

    return 0; 
} 

この出力は:

Signalled! 
<some valid non-null address> 
00000000 
+0

お返事ありがとうございます!!私は同様の行を考えていました。私は、ディスパッチャでshared_ptrの処理を行うために使用できるリスナーへのポインタベクトルを持たなければなりません。しかし、私はweak_ptrのベクトルを理解していないようです。 – Yeshvanthni

+0

これらは対象外のリスナーに過ぎません。ベクターに格納する必要はありません。 Subjectは明示的なデストラクタを必要としないことに注意してください。インスタンスが範囲外になり破棄されると、その内部ベクトルと内部のすべてのshared_ptrsも破壊されます。 –

+0

weak_ptrそのものがよくわからない場合は、こちらをご覧ください:http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/weak_ptr.htm –

0

私はブーストscoped_connectionを使用する方が良いと思います。このオブジェクトはあなたが探しているもののために設計されています。

リストにスコープ接続を保存することができます。リストの所有者が死亡すると、スコープ接続のデストラクタが呼び出され、自動的にオブジェクトがシグナルスロットから切断されます。ここ

読む詳細:

http://www.boost.org/doc/libs/1_46_1/doc/html/boost/signals2/scoped_connection.html

関連する問題