本文主要是介绍Qt: 详细理解delete与deleteLater (避免访问悬空指针导致程序异常终止),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
珍爱生命,远离悬空指针。
正文
delete
- 立即删除:调用
delete
后,对象会立即被销毁,其内存会立即被释放。 - 调用顺序:对象的析构函数会被立即调用,销毁该对象及其子对象。
- 无事件处理:如果在对象销毁过程中还涉及到信号和槽、事件处理等,直接
delete
可能会导致问题,尤其是在对象正在处理事件时。 - 适用场景:适用于在确定对象已经不再被使用的情况下,并且不涉及异步处理或事件循环中的删除。
MyWidget *widget = new MyWidget();
delete widget; // 立即删除对象并释放内存
deleteLater
- 延迟删除:
deleteLater
并不会立即销毁对象,而是将销毁任务放入 事件队列,等到当前和其他相关的事件处理完成后才会销毁对象。 - 异步安全:它适用于对象正在执行某些操作(例如正在响应信号、槽或事件)的情况下,防止对象在事件处理过程中被意外删除而导致崩溃。
- 事件循环依赖:
deleteLater
依赖于事件循环(event loop),只有在事件循环的下一个迭代时才会删除对象。如果没有事件循环,该对象可能不会被删除。 - 适用场景:适用于正在处理事件或信号槽连接的对象,或者需要确保对象在当前操作结束后才安全地删除。
MyWidget *widget = new MyWidget();
widget->deleteLater(); // 延迟删除,等到事件处理完成后才会销毁
不同点总结
-
删除时机:
delete
是同步的,立即删除对象。deleteLater
是异步的,等到事件循环完成后再删除对象。
-
使用场景:
delete
适合在确定对象不会再被使用时直接销毁。deleteLater
适合对象正在处理事件或信号时使用,避免在对象处理完毕之前被删除。
-
事件安全性:
delete
可能会在处理事件时导致崩溃,因为对象会立即被删除。deleteLater
避免了这个问题,确保事件处理完成后再销毁对象。
例子
例如,如果你有一个正在运行的 QWidget
,它正在处理某个事件,这时使用 delete
会立即删除该对象,导致未定义行为或崩溃。如果用 deleteLater
,对象会等到事件处理完成后再删除。
void MyWidget::someSlot() {// 如果这里直接 delete this,可能导致崩溃// delete this;// 使用 deleteLater 可以安全地删除对象this->deleteLater();
}
相同点总结
二者在销毁对象后,尤其是指针指向的对象,只是释放了指针指向的内存,指针仍然会保留其先前的地址,其指针本身并不会被置为nullptr
,此时指针就处于悬空状态,被称为悬空指针,网上和书上说访问悬空指针会造成未定义行为,我遇到最多的情况就是程序异常终止
,让你摸不着头脑。所以说在将指针释放掉后,一定一定一定要指向nullptr
,这在你编程的时候会避免很多问题。
小结
这篇关于Qt: 详细理解delete与deleteLater (避免访问悬空指针导致程序异常终止)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!