Boost Signals2销毁Slot对象后Slot仍触发问题咨询
为什么销毁Slot对象后Boost.Signals2的Slot仍会被触发?
核心原因
你当前的代码中,Boost.Signals2没有追踪到Slot对象的生命周期,所以即便销毁了MySlot实例,信号与槽的连接依然存在,调用信号时会触发非法的对象成员函数调用(属于未定义行为,你的测试中刚好输出了内容,但实际可能导致崩溃)。
Boost文档中提到的“被slot追踪的对象被销毁时触发断开连接”,并非指任意绑定了成员函数的对象——要让Boost自动追踪对象生命周期,必须满足以下条件之一:
- Slot对象继承自
boost::signals2::trackable - 使用
std::shared_ptr/boost::shared_ptr管理Slot对象,并通过boost::bind或std::bind结合智能指针绑定成员函数
你的测试代码问题点
你用裸指针auto* slot = new MySlot;创建对象,直接绑定成员函数时,Boost无法感知这个裸指针的销毁,因此不会自动断开连接。
class MySignal { public: boost::signals2::signal<void ()> signal_one; boost::signals2::signal<void ()> signal_two; }; class MySlot { public: void SlotOne() { std::cout << "slot_one" << std::endl; } void SlotTwo() { std::cout << "slot_two" << std::endl; } }; int main() { MySignal signal; auto* slot = new MySlot; auto c = connect(signal.signal_one, slot, &MySlot::SlotOne); // c.disconnect(); if (slot != nullptr) { delete slot; slot = nullptr; } signal.signal_one(); return 0; }
修正方案
方案1:让Slot类继承boost::signals2::trackable
trackable类会自动管理连接,当对象销毁时,所有绑定到该对象成员函数的连接都会自动断开:
#include <boost/signals2/signal.hpp> #include <iostream> class MySignal { public: boost::signals2::signal<void ()> signal_one; boost::signals2::signal<void ()> signal_two; }; // 继承trackable让Boost自动追踪生命周期 class MySlot : public boost::signals2::trackable { public: void SlotOne() { std::cout << "slot_one" << std::endl; } void SlotTwo() { std::cout << "slot_two" << std::endl; } }; int main() { MySignal signal; auto* slot = new MySlot; auto c = connect(signal.signal_one, slot, &MySlot::SlotOne); delete slot; slot = nullptr; signal.signal_one(); // 此时不会触发SlotOne,连接已自动断开 return 0; }
方案2:使用智能指针管理Slot对象
通过shared_ptr结合boost::bind,让Boost追踪智能指针的生命周期:
#include <boost/signals2/signal.hpp> #include <boost/bind/bind.hpp> #include <iostream> #include <memory> class MySignal { public: boost::signals2::signal<void ()> signal_one; boost::signals2::signal<void ()> signal_two; }; class MySlot { public: void SlotOne() { std::cout << "slot_one" << std::endl; } void SlotTwo() { std::cout << "slot_two" << std::endl; } }; int main() { MySignal signal; std::shared_ptr<MySlot> slot = std::make_shared<MySlot>(); // 使用boost::bind绑定智能指针和成员函数 signal.signal_one.connect(boost::bind(&MySlot::SlotOne, slot)); slot.reset(); // 销毁Slot对象 signal.signal_one(); // 不会触发SlotOne,连接已自动断开 return 0; }
Boost文档相关内容引用
Signal/slot断开连接会在以下任一条件发生时触发:
- 通过connection的disconnect方法、signal的disconnect方法或scoped_connection的析构函数显式断开连接。
- 被slot追踪的对象被销毁。
- signal被销毁。
内容的提问来源于stack exchange,提问作者D_Latch
相关产品推荐
相关产品推荐

