我需要删除这些指针吗?

8
这是MainWindow类,我调用并使用show()函数使其对用户可见。
class MainWindow : public QMainWindow
{
    Q_OBJECT

    QWidget *centralWidget;
    QGridLayout* gridLayout;
    QGridLayout* infoBoxLayout;
    QHBoxLayout* buttonGroup;
    QHBoxLayout* subCategoryLayout;
    //... more widgets

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void setupUi();
    void setupConnections();

private slots:
    void add();
    void edit();
    void remove();
    void find();
    void clearAll();
    void screenshotDesktop();
    void screenshotApp();

    void currentSubCategoryChanged( const QString& );
    void curretCategoryChanged( const int );

    void keyPressEvent( QKeyEvent * );

};

我为每个小部件(即宏Q_OBJECT后面的指针)创建了一个新对象,并使用new在堆上分配内存。但是,在程序中没有删除它们。这会导致Qt中的内存泄漏吗?或者,当销毁类时,Qt中的某些内容会自动删除它们吗?


你在这些对象的构造函数中传递了什么作为第一个参数? - avakar
2
如果您将它们添加到布局中,父窗口(MainWindow)将负责释放内存。 - sumeet
注意:对于这样的指针,将其包装到QPointer类中是一个很好的做法。不需要对代码进行任何更改,但是您将受到保护,以防止访问无效的指针。 - Dmitry Sazonov
3个回答

14

如果一个小部件有一个已经设置的父级,则Qt将处理删除该小部件。 在MainWindow的情况下,当您关闭它时,MainWindow及其子项将被清除,因此请将父级传递给小部件的构造函数:

QHBoxLayout* buttonGroup = new QHBoxLayout(this); // where this is the parent (MainWindow)
如果您创建了像这样的 Widget:-
QHBoxLayout* buttonGroup = new QHBoxLayout;

如果没有在父级组件中传递,它将不会被清理,您需要自己处理。


1
父级在创建时不必指定 - 按钮也可以稍后添加为子级。 - Angew is no longer proud of SO
2
@Davlog 如果您设置了父对象,就不能手动删除它们。您只能删除您拥有的内容。Qt 父子关系方案包括所有权。一旦您设置了小部件的父对象,您不再拥有它,而是由其父对象拥有。 - Angew is no longer proud of SO
1
@Davlog 如果用户界面已经删除了小部件,而你再次删除它,你的程序将会出现未定义行为(例如崩溃)。 - user2249683
1
@DieterLücking 但是Qt在处理被销毁的对象方面非常聪明:它们(以及子对象)会自动从层次结构中移除,并且所有连接都会被删除。 - ratchet freak
1
@Merlin069:仅仅创建没有父对象的QObject(如:QWidgets)并不会导致内存泄漏,这是错误的说法。Qt经常自动为这些对象设置父对象。例如,将小部件添加到布局中会将其转移给底层小部件作为父对象,如果布局在小部件上设置,则立即进行此操作,否则在将布局添加到小部件时稍后再执行。 - Kuba hasn't forgotten Monica
显示剩余4条评论

5

如果您将它们添加到GUI层次结构中,那么当MainWindow被删除时,它们将被清除。

这是因为父项会对其子项拥有所有权(这是通过GUI的各种添加操作设置的)。

因此,this->add(centralWidget);会调用centralWidget->setParent(this);,这将使当MainWindow被删除时,centralWidget也被删除。

您可以自行删除QObjects,但请注意悬空指针(使用QPointer将有所帮助)。我建议使用deleteLater()来确保在指针仍然存在于堆栈上时不会出现奇怪的行为。

有关对象树的更多信息请参见此处


2
自动的通过父子关系进行内存管理是由 QObject 来完成的。 QWidget 恰好就是一个 QObject,并且恰好具有父窗口的小部件与其父窗口具有相同的基础 QObject。
拥有子对象的 QObject 在其析构函数中会自动删除其子对象。
一个 QObject 或者 QWidget 可以被另一个对象接收。例如,将小部件添加到布局中将自动将它们重新定位到设置在布局上的小部件。即使布局尚未设置小部件,当您将布局添加到小部件(或已经设置了小部件的布局)时,重新定位也将在此时完成。这非常聪明,节省了很多打字时间,并减少了错误的可能性。
向另一个小部件添加小部件的惯用、最少打字的方式是:
MyWidget() {
  QLayout * layout = new QHBoxLayout(this); // set a layout on this widget
  layout->addWidget(new QLabel("foo")); // the label is reparented to this
  layout->addWidget(new QPushButton("bar")); // the button is reparented to this
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接