升压:: signals2 - 对象的descruction与槽(Boost::signals2

2019-08-16 23:43发布

试想一下:

#include <boost/signals2.hpp>
#include <iostream>

struct object_with_slot
{
void operator()()
{
   std::cout << "Slot called!" << std::endl;
   member = 50500;
}
int member;
};


int main()
{
boost::signals2::signal<void ()> sig;

object_with_slot * ptr = new object_with_slot;
sig.connect(*ptr);

delete ptr;

sig();
}

输出是“叫老虎!” 并没有崩溃或任何东西。 这就是为什么我有几个问题:

1)为什么没有崩溃?

2)为什么有即使槽函数分配的东西对象不存在不崩溃?

3)如何让自动信号跟踪其槽的寿命是多少? 我的意思是,当槽被破坏,它就会断开。

问题3号是最重要的,因为我需要实现观察者模式,而且往往观察员(槽)一辈子都不会是静态的(对于整个时间的应用程序运行时)。

Answer 1:

1)你是幸运的。 如果没有,你会得到一个分段错误。

2)存储器为不以任何方式被覆盖。

3)你可以使用插槽::跟踪,当跟踪对象被删除自动断开。 Boost.Signals2可以跟踪由升压:: shared_ptr的管理对象。

#include <boost/signals2.hpp>
#include <boost/shared_ptr.hpp>

struct object_with_slot
{
    void operator()()
    {
       std::cout << "Slot called!" << std::endl;
       member = 50500;
    }
    int member;
};

//
int main()
{
    typedef boost::signals2::signal<void ()> sig_type;
    sig_type sig;

    {
        boost::shared_ptr<object_with_slot> ptr(new object_with_slot);
        sig.connect(sig_type::slot_type(*ptr).track(ptr));

        // 'object_with_slot' managed by ptr is destroyed
    }

    sig(); // 'object_with_slot' not called here.

    return 0;
}

更新:
添加代码,用于跟踪的std :: shared_ptr的和std :: weak_ptr的对象:

#include <memory>
#include <boost/signals2.hpp>

// added specializations for std::weak_ptr and std::shared_ptr
namespace boost
{
  namespace signals2
  {
    template<typename T> struct weak_ptr_traits<std::weak_ptr<T> >
    {
      typedef std::shared_ptr<T> shared_type;
    };

    template<typename T> struct shared_ptr_traits<std::shared_ptr<T> >
    {
      typedef std::weak_ptr<T> weak_type;
    };
  }
}

struct object_with_slot
{
    void operator()()
    {
       std::cout << "Slot called!" << std::endl;
       member = 50500;
    }
    int member;
};

//
int main()
{
    typedef boost::signals2::signal<void ()> sig_type;
    sig_type sig;

    std::shared_ptr<object_with_slot> ptr(new object_with_slot);
    sig.connect(sig_type::slot_type(*ptr).track_foreign(ptr)); // ptr is tracked

    sig();

    return 0;
}


Answer 2:

图1和2)事实上,它是一个未定义的行为。 您所使用的引用操作,现在连有object_with_slot的价值,它的地址是免费的内存管理器分配给任何其他进程。 巧合的是它仍然是一个“有效地址”。 和PTR自由分配给无故内存泄漏任何其他值。

尝试这样的事情,你会看到,每次爆炸

#include <boost/signals2.hpp>
#include <iostream>

struct object_with_slot
{
    object_with_slot()
    {
        member = new int(10);
    }

    ~object_with_slot()
    {
        delete member; //comment this line and everything works again
    }
    void operator()()
    {
        std::cout << "Slot called!" << std::endl;
        *member = 50500; //it was destroyed above
    }
    int *member;
};


int main()
{
    boost::signals2::signal<void ()> sig;

    object_with_slot * ptr = new object_with_slot;
    sig.connect(*ptr);

    delete ptr;
    ptr = 0x0;

    sig();
}

3)你可以把object_with_slot的析构函数的另一个信号,那么它可以通知时,它被调用。



Answer 3:

很危险的例子中给出。 看一看:

#include <iostream>
#include <memory>
#include <boost/signals2.hpp>

struct object_with_slot
{
    object_with_slot() {
        std::cout << "ctor\n";
    }

    object_with_slot(const object_with_slot &) {
        std::cout << "cctor\n";
    }

    ~object_with_slot() {
        std::cout << "dtor\n";
    }

    void operator()()
    {
       std::cout << "Slot called!" << std::endl;
       member = 50500;
    }
    int member;
};

//
int main()
{
    typedef boost::signals2::signal<void ()> sig_type;
    sig_type sig;

    std::shared_ptr<object_with_slot> ptr(new object_with_slot);
    sig.connect(sig_type::slot_type(*ptr).track_foreign(ptr)); // ptr is tracked

    sig();

    return 0;
}

您如何看待,有什么了这段代码(G ++ 4.8.1,libboost 1.54)?

ctor
cctor
cctor
cctor
cctor
cctor
cctor
cctor
cctor
dtor
dtor
dtor
dtor
dtor
cctor
dtor
cctor
dtor
dtor
dtor
cctor
dtor
Slot called!
dtor
dtor

我不认为,这种行为预期。 因为我们传递的副本(按价值计算) *ptr (实例object_with_slot )的connect方法。 它可能会解决,例如,通过引用包装:

sig.connect(sig_type::slot_type(boost::ref(*ptr)).track_foreign(ptr)); // ptr is tracked

小心模板和类型。



文章来源: Boost::signals2 - descruction of an object with the slot