在QT中所有权是对还是错

Is there a right or wrong for ownership in Qt

本文关键字:所有权 QT      更新时间:2023-10-16

我想编写"现代C " QT应用程序,这意味着尽可能多地使用RAII。因此,我问自己是否可以安全地使用自动分配:

#include <QApplication>
#include <QtWidgets>
int main(int argc, char **argv) {
    QApplication app{argc, argv};
    QWidget window{};
    window.setWindowTitle("Der eine Knopf");
    QPushButton button{"Ende"};
    QObject::connect( &button, SIGNAL(clicked()), &app, SLOT(quit()));
    QVBoxLayout layout{};
    layout.addWidget(&button);
    window.setLayout(&layout);
    window.show();
    return app.exec();
}

原始教程代码有很多指针和堆:

#include <QApplication>
#include <QtWidgets>
int main(int argc, char **argv) {
  QApplication app{argc, argv};
  QWidget window{};
  window.setWindowTitle("Hallo Qt");
  QPushButton button = new QPushButton("Ende");
  QObject::connect( button, SIGNAL(clicked()),
      &app, SLOT(quit()));
  QVBoxLayout *layout = new QVBoxLayout;
  layout->addWidget(button);
  window.setLayout(layout);
  window.show();
  return app.exec();
}

我一般都知道QT的QObject的所有权概念。因此,我认为第二个示例是正确的。我认为setLayoutaddWidget也更改所有权,因此我作为客户不需要明确的delete

假设我想知道 - 为什么我的第一个示例会起作用?如果这些方法获得所有权,他们是否最终不会delete他们新收购的孩子?如果他们这样做,我的程序会不会崩溃,因为对象被删除了两次?(该程序不会崩溃,我会提到。但是那可能是偶然的,对吗?(

我现在非常困惑谁拥有谁以及它如何工作,我不知道它如何。我听到的一条规则是" QT会照顾好" - 但是"什么"?而不是什么?

好吧,显然我是QT的新手,我想要的是对QObject的构造函数和破坏者计数的一些见解。或每次施工和/或破坏的消息。QT中是否有这样的设施?

如果您查看对象树和所有权,则使用自动分配时,必须注意创建顺序。本地对象的破坏者以其构造函数的相反顺序调用

所以在您的示例中:

int main(int argc, char **argv) {
    QApplication app{argc, argv};
    QWidget window{};
    window.setWindowTitle("Der eine Knopf");
    QPushButton button{"Ende"};
    QObject::connect( &button, SIGNAL(clicked()), &app, SLOT(quit()));
    QVBoxLayout layout{};
    layout.addWidget(&button);
    window.setLayout(&layout);
    window.show();
    return app.exec();
}

在这里您创建一个称为windowQWidget对象。然后,您创建一个QPushButton。您将布局设置为小部件,然后将button添加到该布局。布局将自动将window设置为button的父。但是,当您退出应用程序并结束范围时,button将首先被销毁。在破坏之后,它将从window的儿童名单中删除。因此不会被销毁两次。

但是,如果您在window之前创建button,则window将在button之前被销毁,并且还将摧毁所有孩子。这意味着它也将调用button的攻击函数。此后,button的驱动器将在范围范围内再次被调用。所以在这里您会有一个大问题。