关于 Qt 中的信号和槽,delete 和 deleteLater 如何工作? [英] How delete and deleteLater works with regards to signals and slots in Qt?

查看:165
本文介绍了关于 Qt 中的信号和槽,delete 和 deleteLater 如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个 QNetworkReply 类的对象.有一个插槽(在某个其他对象中)连接到它的完成()信号.信号是同步的(默认的).只有一个线程.

There is an object of class QNetworkReply. There is a slot (in some other object) connected to its finished() signal. Signals are synchronous (the default ones). There is only one thread.

有时我想摆脱这两个对象.没有更多的信号或任何来自他们的东西.我要他们走.好吧,我想,我会用

At some moment of time I want to get rid of both of the objects. No more signals or anything from them. I want them gone. Well, I thought, I'll use

delete obj1; delete obj2;

但我真的可以吗?~QObject 的规格说明:

But can I really? The specs for ~QObject say:

在挂起事件等待传递时删除 QObject 会导致崩溃.

Deleting a QObject while pending events are waiting to be delivered can cause a crash.

什么是未决事件"?这是否意味着当我调用我的 delete 时,已经有一些待处理事件"要传递并且它们可能会导致崩溃而我无法真正检查是否有任何事件?

What are the 'pending events'? Could that mean that while I'm calling my delete, there are already some 'pending events' to be delivered and that they may cause a crash and I cannot really check if there are any?

假设我打电话:

obj1->deleteLater(); obj2->deleteLater();

为了安全.

但是,我真的安全吗?deleteLater 添加一个事件,当控制到达那里时,该事件将在主循环中处理.obj1obj2 是否有一些未决事件(信号)已经存在,等待在主循环中处理 before deleteLater 将被处理?那将是非常不幸的.我不想编写代码检查有点删除"状态并忽略所有插槽中的传入信号.

But, am I really safe? The deleteLater adds an event that will be handled in the main loop when control gets there. Can there be some pending events (signals) for obj1 or obj2 already there, waiting to be handled in the main loop before deleteLater will be handled? That would be very unfortunate. I don't want to write code checking for 'somewhat deleted' status and ignoring the incoming signal in all of my slots.

推荐答案

如果你遵循两个基本规则,删除 QObjects 通常是安全的(即在正常实践中;可能存在我不知道 atm 的病态情况):

Deleting QObjects is usually safe (i.e. in normal practice; there might be pathological cases I am not aware of atm), if you follow two basic rules:

>

  • 切勿从要删除的对象中删除由(同步,连接类型直接")信号直接或间接调用的插槽或方法中的对象.例如.如果您有一个带有信号 Operation::finished() 和槽 Manager::operationFinished() 的操作类,您不希望删除在该槽中发出信号的操作对象.发出finished()信号的方法可能会在发出后继续访问this"(例如访问成员),然后对无效的this"指针进行操作.

    • Never delete an object in a slot or method that is called directly or indirectly by a (synchronous, connection type "direct") signal from the object to be deleted. E.g. if you have a class Operation with a signal Operation::finished() and a slot Manager::operationFinished(), you don't want delete the operation object that emitted the signal in that slot. The method emitting the finished() signal might continue accessing "this" after the emit (e.g. accessing a member), and then operate on an invalid "this" pointer.

    同样,永远不要删除从对象的事件处理程序同步调用的代码中的对象.例如.不要在 SomeWidget::fooEvent() 或从那里调用的方法/插槽中删除 SomeWidget.事件系统将继续在已删除的对象上运行 -> 崩溃.

    Likewise, never delete an object in code that is called synchronously from the object's event handler. E.g. don't delete a SomeWidget in its SomeWidget::fooEvent() or in methods/slots you call from there. The event system will continue operating on the already deleted object -> Crash.

    两者都很难追踪,因为回溯通常看起来很奇怪(就像访问 POD 成员变量时崩溃一样),尤其是当您有复杂的信号/槽链时,删除可能发生在最初由信号启动的几步之后或来自已删除对象的事件.

    Both can be tricky to track down, as the backtraces usually look strange (Like crash while accessing a POD member variable), especially when you have complicated signal/slot chains where a deletion might occur several steps down originally initiated by a signal or event from the object that is deleted.

    这种情况是deleteLater() 最常见的用例.它确保当前事件可以在控件返回到事件循环之前完成,然后事件循环会删除对象.另一个,我发现通常更好的方法是使用排队连接/QMetaObject::invokeMethod( ..., Qt::QueuedConnection ) 推迟整个操作.

    Such cases are the most common use case for deleteLater(). It makes sure that the current event can be completed before the control returns to the event loop, which then deletes the object. Another, I find often better way is defer the whole action by using a queued connection/QMetaObject::invokeMethod( ..., Qt::QueuedConnection ).

    这篇关于关于 Qt 中的信号和槽,delete 和 deleteLater 如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆