Q&A-2:
Q:
博主你说“在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。”,可是您又在《hello world》中拒了一个在堆上创建QLabel的反例。求解惑。
A:
在 main() 函数中,不应该在堆上面创建对象。这是由于如果在 main() 中在堆上面创建对象,app.exec() 函数是一个死循环,创建出的这个对象没有办法被 delete(不开启事件循环,组件就不能显示,不显示组件就不能 delete,否则你还创建它干什么呢?)。另外的原因是,由于我们的 QApplication 是在栈上面创建的,在堆上面创建的 QLabel 对象生命周期要长于 QApplication,这在 Qt 中是应该避免的。而对于我们自己定义的组件就没有这个问题,因为不在 main() 函数中,我们始终可以保证最晚在关闭时销毁(当然是不发生内存泄露的情况下),也就没有这个问题。
Q:
为什么我们自己定义的组件不在 main() 函数中,可以解释一下吗?
A:
我们自己定义的组件不在 main() 函数直接被调用,而是通过 MainWindow 之类的顶层窗口调用,而 MainWindow 通常直接被 main() 实例化。因此,只要保证了最顶层的 MainWindow 能够正确释放,并且 parent 能够连接成链,就可以保证每一个组件被正确释放
Tips:
当一个QObject
对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。Qt 保证的是,任何对象树中的 QObject
对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()
列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject
会被 delete 两次,这是由析构顺序决定的。