delete和deleteLater如何处理Qt中的信号和插槽?

sta*_*ach 73 qt slot qt-signals

有一个类QNetworkReply的对象.有一个插槽(在某些其他对象中)连接到其finished()信号.信号是同步的(默认值).只有一个主题.

在某些时刻,我想摆脱两个对象.没有更多的信号或任何东西.我希望他们走了.好吧,我想,我会用的

delete obj1; delete obj2;
Run Code Online (Sandbox Code Playgroud)

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

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

什么是"待定事件"?这是否意味着当我打电话给我时delete,已经有一些"未决事件"要发送,并且它们可能会导致崩溃,我无法确定是否有任何?

所以我要说我打电话:

obj1->deleteLater(); obj2->deleteLater();
Run Code Online (Sandbox Code Playgroud)

为了安全起见.

但是,我真的很安全吗?该deleteLater补充说,将在主回路控制时到达那里进行处理的事件.是否有一些待处理事件(信号)obj1obj2已经存在,等待在处理deleteLater 之前在主循环中处理?那将是非常不幸的.我不想编写"有点删除"状态的代码检查,并忽略所有插槽中的传入信号.

Fra*_*eld 66

如果您遵循两个基本规则,删除QObject通常是安全的(即在正常练习中;可能存在我不知道atm的病理情况):

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

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

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

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


lia*_*iaK 20

接下来的两行文件说明了答案.

来自~QObject,

等待传递挂起事件时删除QObject可能会导致崩溃.如果QObject存在于与当前正在执行的不同的线程中,则不能直接删除它.改为使用deleteLater(),这将导致事件循环在所有挂起事件传递给它之后删除该对象.

它特别告诉我们不要从其他线程中删除.由于您有一个单线程应用程序,因此可以安全删除QObject.

另外,如果你必须在多线程环境中删除它,使用deleteLater()它将删除你QObject曾经完成所有事件的处理.

  • 我的第二个场景怎么样?在我调用deleteLater后,仍然可以调用对象中的插槽吗? (5认同)

Pio*_*ost 15

您可以在阅读有关Delta对象规则之一的问题中找到答案:

信号安全(SS).
从一个信号调用的槽内调用对象上的方法(包括析构函数)必须是安全的.

分段:

QObject的核心是支持在发送信号时被删除.为了利用它,您只需确保您的对象在删除后不会尝试访问任何自己的成员.但是,大多数Qt对象不是以这种方式编写的,也不需要它们.因此,如果您需要在其中一个信号中删除对象,建议您始终调用deleteLater(),因为"删除"只会使应用程序崩溃.

不幸的是,你应该使用'delete'和deleteLater()并不总是很清楚.也就是说,代码路径具有信号源并不总是显而易见的.通常,您可能有一块代码块在某些对象上使用"删除",这些代码在今天是安全的,但在将来的某个时刻,同一代码块最终会从信号源调用,现在突然您的应用程序崩溃了.解决这个问题的唯一一般方法是始终使用deleteLater(),即使一眼就看起来没必要.

一般来说,我认为Delta对象规则是每个Qt开发人员必读的.这是一本优秀的阅读材料.