在构造器的初始化列表中使用"this"对Qt是否特别危险?

Is using "this" in contructor's initialization list specificly dangerous with Qt?

本文关键字:是否 Qt 危险 this 初始化 列表 构造器      更新时间:2023-10-16

我需要关于"这个"主题的可靠信息:

class MyClass, public QWidget
{
public:
    MyClass( QWidget * parent = NULL )
         :QWidget( parent ),
         mpAnotherWidget( new QWidget( this ) ){};
private:
    QWidget * mpAnotherWidget;
};

当然,调用构造函数或初始化列表中的虚拟函数是个坏主意。问题是:这能编码吗

mpAnotherWidget( new QWidget( this ) )

导致未定义的行为?!如果是:为什么?

如果可以的话,请引用你的消息来源!谢谢

这取决于QWidget对给定指针的处理。只要被调用的代码不访问底层对象,就可以绕过对半构造对象的引用或指针。您需要查看QWidget的文档,以了解它是接触对象还是仅存储指针。


在Qt的特殊情况下,读取文档时,它调用QWidget的构造函数,参数类型为QWidget*,而this仅用于强制转换为基指针。12.7/3中保证获得指向基的指针,因为转换的要求是X的构造及其直接或间接衍生自B的所有直接或间接基的构造都应已开始。然后,指针被传递给QWidget构造函数,该构造函数可以以任何方式使用它,因为在mpAnotherWidget的构造函数启动之前,基本QWidget的构造函数已经完成。

一般来说,这是一种不常见的技术,而且有风险,因为不清楚其他代码可能有什么期望。

但正如您正确指出的,这是Qt代码。在这里,向构造函数传递指针是很常见的,也是意料之中的事。您的窗口由许多相互了解的对象组成。

特别是,QWidget可以有其他QWidget作为父级,这是通过将父级指针传递给子级来支持的。由于父级通常是构造子级的类,因此父级指针仅为this。所以你的代码是完全正常的Qt风格。

现在,这里安全吗?如书面所述,是的。子窗口小部件QWidget::QWidget的构造函数假设父指针确实指向已构建的QWidget,在您的示例中也是如此。但它并没有假设更多。怎么可能呢?QWidget对你们班一无所知。特别是,它甚至不能调用纯虚拟方法,因为QWidget没有这些方法。

如果指针不立即使用,而是存储起来以备将来使用,这是可以的。

但在派生QObject的情况下,传递指针是为了建立父子对象所有权,这意味着指针将在其指向的对象完全构造之前使用。因此,这是一种未定义的行为——任何事情都可能发生,如果发生了,那将是糟糕的。