You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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断开连接会在以下任一条件发生时触发:

  1. 通过connection的disconnect方法、signal的disconnect方法或scoped_connection的析构函数显式断开连接。
  2. 被slot追踪的对象被销毁。
  3. signal被销毁。

内容的提问来源于stack exchange,提问作者D_Latch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:49:53