2013-09-26 130 views
3

这是我调用的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 *); 

}; 

我对于每个插件一个新的与new堆对象(宏Q_OBJECT后这些指针)创建。但是,我并没有在程序中的任何地方删除它们。这是否会导致Qt中的内存泄漏?或者在Qt中有一些东西在销毁该类时自动删除它们?

+0

你是怎么传递的第一个参数对这些对象的构造函数? – avakar

+0

@avakar nothing – Davlog

+2

如果您将这些添加到布局中,父级(MainWindow)将负责释放内存。 – sumeet

回答

9

如果一个小部件有一个父集,那么Qt将处理删除该小部件。 在主窗口的情况下,当您关闭它,在主窗口和它的孩子们将被清理,所以父母传递给小部件的构造: -

QHBoxLayout* buttonGroup = new QHBoxLayout(this); // where this is the parent (MainWindow) 

如果创建一个Widget像这样: -

QHBoxLayout* buttonGroup = new QHBoxLayout; 

并没有通过父母,那么它不会被清理,你将不得不自己处理。

+1

不必在创建时指定父项 - 稍后也可以将小部件添加为小孩。 – Angew

+0

好的。当我设置父项,手动删除它们仍然可以或仅仅是不必要的?只是为了安全起见,我不想在我的程序中发生内存泄漏。 – Davlog

+1

@Davlog如果你设置父级,你必须*不*手动删除它们。你只能删除你拥有的东西。 Qt亲子计划包括所有权。一旦你设置了一个小部件的父项,你就不拥有它的父项了。 – Angew

5

,如果你把它们添加到GUI层次结构中那么当MainWindow被删除

这是因为父母承担起对子女的所有权(其中设置的各种GUI的增加),他们将被清理

所以this->add(centralWidget);将调用centralWidget->setParent(this);这将让centralWidgetMainWindow被删除

被删除,你可以自由地删除自己的QObject但要小心,悬摆指针(QPointer将在这里帮助)。尽管我建议使用deleteLater()确保指针仍然位于堆栈上时不会出现奇怪的行为。

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

1

通过父子关系的自动内存管理是由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 
}