1

ブースト信号のようなクラスを作成しようとしています (C++ を学習するための練習として)。そして、使用するenable_shared_from_thisと、常にデストラクタでクラッシュすることがわかりました。コードは次のとおりです(vs2012 update 2を使用しています):

これについて何かコメントはありますか?の行 ( )shared_from_this()のコメントを外すと、すべて正常に動作するため、この問題が発生するはずです。auto this_ = shared_from_this();signal_connection::disconnect

を呼び出す前に、少なくとも 1 つの有効な shared_ptr が必要であることはわかっていshared_from_this()ます。私のコードはこれを満たす必要があります。

コード:

    #include <memory>
    #include <map>

    class slot_manager;

    class signal_connection: public std::enable_shared_from_this<signal_connection>
    {
    public:
        signal_connection(slot_manager* manager)
            :manager_(manager)
        {}
    public:
        void disconnect() ;
    private:
        slot_manager* manager_;
    };

    class slot_manager
    {
    public:
        typedef std::shared_ptr<signal_connection> connection_type;
        typedef std::map<connection_type, int> map_type;
        typedef map_type::value_type map_value_type;
    public:
        void connect(int slot)
        {
            std::shared_ptr<signal_connection> c(new signal_connection(this));
            slots_.insert(map_value_type(c, slot));
        }
        ~slot_manager()
        {
            auto iter = slots_.begin();
            map_type::iterator iter2 = slots_.end();
            while (iter != slots_.end())
            {
                iter2 = iter++;
                iter2->first->disconnect();
            }
        }
        void disconnect(std::shared_ptr<signal_connection> connection)
        {
            auto c = slots_.find(connection);
            if (c != slots_.end())
            {
                slots_.erase(c);
            }
        }
    protected:
        map_type slots_;
    };

    void signal_connection::disconnect() 
    {
        if (manager_ != nullptr)
        {
            //auto this_ = shared_from_this();
            manager_->disconnect(shared_from_this());
            manager_ = nullptr;
        }
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
        slot_manager x;
        x.connect(1);
    return 0;
    }
4

1 に答える 1

7

disconnect()問題は、その manager を に設定する前にsignal_connection が破棄されnullptr、アクセス違反が発生することです。つまり、manager の disconnect への呼び出しによって発生します。これは、マネージャーがshared_ptr接続のみを保持しているためですerase()。オブジェクトはそれ自体を存続させません。もちろん、その行のコメントを外さない限り。this_問題を回避するのに十分なだけ長生きします。

于 2013-06-27T12:59:49.463 に答える