c++ 升压信号断开问题:在插槽对象被销毁后,插槽仍然可以被触发

cigdeys3  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(191)

到目前为止,我遇到了同样的问题。boost web中的文档说断开连接发生在“插槽跟踪的对象被破坏”时。然而,我测试了它并不以这种方式工作。所以我更喜欢手动断开连接,虽然有点麻烦。
我的测试代码:

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;
}

字符串
有谁能告诉我,为什么我已经销毁了插槽对象,但插槽仍然可以被触发?
我只能说服自己,boost的文档说在某些情况下会发生“断开连接”,但没有说它会自动发生。
下面的文字是boost文档所说的:
出现以下任何情况时,信号/插槽断开:
1.直接通过连接的disconnect方法显式断开连接,或通过信号的disconnect方法或scoped_connection的析构函数间接断开连接。
2.插槽跟踪的对象被销毁。
3.信号被破坏了。

n6lpvg4x

n6lpvg4x1#

boost web中的文档说,当"插槽跟踪的对象被破坏“时,就会发生断开连接。但是,我测试了一下,它并没有以这种方式工作。所以我更喜欢手动断开连接,虽然有点麻烦。
这里的关键词是“跟踪”。通过使从trackable class继承的插槽对象:

class MySignal : public boost::signals2::trackable  {
public:
    boost::signals2::signal<void ()> signal_one;
    boost::signals2::signal<void ()> signal_two;
};

字符串
在这里当你这样连接的时候:

auto c = connect(signal.signal_one, slot, &MySlot::SlotOne);


该信号将具有指向slot的指针以进行跟踪。
请注意,对于lambda slot,必须将指针作为附加参数传递,请参见Using boost::signals2::trackable with lambdas
当您不跟踪对象生存期,而调用已删除对象的插槽时,就像在您的示例中一样,您将具有Undefined Behavior。这在正常执行slot时仍然很可能表现出来,因为您没有引用this,并且slot函数是非虚拟的。

相关问题