Qt智能指针和QObject对象树系统(父子系统)结合使用出现的问题

Qt智能指针和QObject对象树系统(父子系统)结合使用出现的问题


Qt的智能指针是在Qt4.5的时候提出来的,目的是为了让Qt应用程序能够摆脱硬编码delete的问题,避免的内存泄漏。但是在我编写程序的时候,发现它和QObject对象树系统(父子系统)相结合屡屡出错。这里以日志的形式记录下来,防止别人再出错。
Qt的智能指针主要有QSharedPointer和QScopedPointer,当然还有其它的类,但是用得较少。QSharedPointer是在Qt4.5的时候引进的,而QScopedPointer是在Qt4.6的时候引进的,我想这是因为Qt开发者看到了Boost或是Loki在智能指针这方面的卓越研究,而决定自己制作一套强大的智能指针吧。Qt的智能指针风格类似Boost,为每种指针提供了一个从字面上很好理解的类来进行封装。但是开发者(包括我)需要注意的是,它包含的对象若是从QObject继承下来的子类,那么就要担心了。在运行的时候一旦智能指针销毁,就会出错,让人摸不着头脑。
原因在于,QObject自有对象树系统(父子系统),它在和其它QObject子类进行交互的时候会将对方的指针保存起来,形成父子关系,最终一个QObject子类指针会形成一个强大的树状结构,当父亲销毁的时候,会先销毁它的孩子(如果它的孩子是通过new操作符在堆上创建的话)。但是智能指针在保有QObject子类的时候会自动调用它的析构函数,从而引起事实上的两次delete,这个时候编译器的就会报错。
那我熟悉的QScopedPointer来说,本来将它用在类的成员中是一个很好的选择,但是由于它保有的是QObject的子类,这个智能指针在和其它QObject子类交互的时候难免会被对方保有原始指针的值,在进入类的析构函数,QScopedPointer保有原始指针的值会被先于释放并置为“已删除”的值0xfeeefeee,这个时候再通过智能指针的自动清理只可能会带来运行错误。在qscopedpointer.h源码中,我们看到QScopedPointerDeleter类的cleanup静态函数并不带有在delete之前的指针的值检测,于是在delete一个无效的指针时,错误发生了。

你可能感兴趣的:(Qt智能指针和QObject对象树系统(父子系统)结合使用出现的问题)