加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在传递的对象被破坏之前发出信号传递QObject指针作为参数是

发布时间:2020-12-16 09:49:14 所属栏目:百科 来源:网络整理
导读:让我们考虑这个简单的例子: Class Emitter: public QObject {...signal: surfaceDestroyed(QObject*);public: void emittingMethod(QObject* surface) { emit surfaceDestroyed(surface); delete surface; }} 我有这种情况的排队连接 connect(emitterObject
让我们考虑这个简单的例子:

Class Emitter: public QObject {
...
signal:
    surfaceDestroyed(QObject*);
public:
    void emittingMethod(QObject* surface) {
        emit surfaceDestroyed(surface);
        delete surface;
    }
}

我有这种情况的排队连接

connect(emitterObject,SIGNAL(surfaceDestroyed(QObject*),receiverObject,SLOT(onSurfaceDestroyed(QObject*)),Qt::QueuedConnection);

在onSurfaceDestroyed方法中,取消引用并使用接收到的QObject

那么问题是这段代码的安全性如何?我在QT网站上已经阅读了很多相关信息,但我仍然没有清楚地了解这个问题.

在我看来,这个代码是不安全的,因为一旦处理了事件循环并且接收器对象访问释放的内存,就会发送信号,然后表面被破坏,而不是事件发生在receiverObject上,因此SIGSEGV

这是真实代码的简化示例,因此很难跟踪崩溃是否会因此而发生.

解决方法

这取决于信号槽连接的类型.如果发送方和接收方属于同一个线程,则默认情况下连接是直接的.在这种情况下,当您发出信号时,将立即调用插槽.信号功能完成后,您可以确定插槽已完成.

当发送方和接收方属于不同的线程时,默认情况下连接排队.在这种情况下,您的代码不安全.可以在调用信号之前调用插槽.即使deleteLater也不会保存这种情况,因为它由发送者的线程的事件循环处理,并且不依赖于其他线程的事件循环.

因此,如果要编写此类代码,请确保对象位于同一个线程中.您可以通过Qt :: DirectConnection选项连接函数以使连接类型更清晰.

如果要使用排队连接,可以发出例如aboutToBe发送者发送的信号.接收器将接收该信号,以某种方式处理它并使用cleanUpCompleted信号进行响应,该信号将触发实际的对象删除.

还要考虑使用标准的QObject :: destroyed信号.它在对象被销毁之前立即调用,但在许多情况下可能很有用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读