June 27, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

[SOLVED] [N00b] Memory management in Qt

 

Hello Qt devs!

I just read this passage in C++ GUI Programming with Qt 4 by Jasmin Blanchette and Mark Summerfiedl:

Qt’s parent-child mechanism is implemented in QObject. When we create an object (a widget, validator, or any other kind) with a parent, the parent adds the object tothe list of its children. When the parent is deleted, it walks through its list of children and deletes each child.

Now, if you take a look at the following code:

  1. #ifndef EMPLOYEELISTDIALOG_H
  2. #define EMPLOYEELISTDIALOG_H
  3.  
  4. #include <QSqlQueryModel>
  5. #include "ui_employeelistdialog.h"
  6.  
  7. class employeeListDialog : public QDialog, private Ui::employeeListDialog
  8. {
  9.     Q_OBJECT
  10.  
  11. public:
  12.     explicit employeeListDialog(QWidget *parent = 0);
  13.  
  14. private:
  15.  
  16.     // Function that initializes employee data models
  17.     void EMPModels();
  18.  
  19.     // Declares some pointers to help query DB
  20.     // when displaying employee information
  21.     QSqlQueryModel *EMPpr;
  22.     QSqlQueryModel *EMPpa;
  23.     QSqlQueryModel *EMPpapr;
  24. };
  25.  
  26. #endif // EMPLOYEELISTDIALOG_H

and

  1. void employeeListDialog::EMPModels()
  2. {
  3.  
  4.  
  5.     // Initially hides everything in the centralWidget area.
  6.     // Widgets will appear when buttons are triggered.
  7.     // Also sets the tabs' label text
  8.  
  9.     /* Queries the database for the present employees and makes
  10.       a model out of it, so a view can be added later */
  11.     EMPpr = new QSqlQueryModel;
  12.     ...
  13.     ...
  14.     /* Same thing for past employees */
  15.     EMPpa = new QSqlQueryModel;
  16.    ...
  17.    ...
  18.  
  19.     /* Same thing for all employeese, past and present */
  20.     EMPpapr = new QSqlQueryModel;
  21.     ...
  22.     ...
  23.    
  24. }

Do I have to write

  1.  EMPpapr = new QSqlQueryModel(this);

so that the pointers get deleted, or are they already handled by Qt?

Also, if I declare some QSqlQuery pointers, which do not specify parents, do I need to delete them manually?

 Signature 

Joey Dumont

11 replies

June 27, 2011

Lukas Geyer Lukas Geyer
Gene Splicer
2074 posts

Parent / child relationships are either established “explicit” by passing a parent to the constructor / calling QObject::setParent() or “implicit” by objects taking ownership of another eg. adding a widget to a layout. Such situations are usually stated in the documentations.

But there is no automatism.

In your case you will have to explicitly set a parent.

June 27, 2011

Chuck Gao Chuck Gao
Lab Rat
342 posts

Basiclly, if your instance has parent object(which is QObject base), it will be deleted when parent be deleted. So, firstly, make sure if it’s QObject-based. If the answer is not, you can delete the pointer in the deconstructor. Or use smart pointer in Qt.

 Signature 

Chuck

June 27, 2011

Chuck Gao Chuck Gao
Lab Rat
342 posts

If you use QML with Qt C++, it’s more complicated. But the core concept you need know is ownership. Also in QtScript. You can also think about if the pointer be deleted twice, and what will happen in Qt.

 Signature 

Chuck

June 27, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Okay.

For instance, when I close a dialog using, say

  1. connect(EMP_closeButton, SIGNAL(clicked()), this, SLOT(close()));

will this call the destructor, or will it just hide the dialog?

Do I need to set Qt::WA_DeleteOnClose? If yes, where do I do that?

Thanks for your incredibly fast reponses, guys!

 Signature 

Joey Dumont

June 27, 2011

Andre Andre
Area 51 Engineer
6031 posts

Yes, you should give your QSqlQueryModel instances an explicit parent. If you do not specify a parent, and none is set automatically (for instance inserting a widget into a layout of a parent widget will take care of parent-child relationships automatically), you need to take care of deleting any object you created on the heap yourself. That probably come down to calling delete on the pointers in the destructor of the class you created them in. Or, as Chuck.Gao suggests, use smart pointers to take care of that for you.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

June 27, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Okay. So since everything (dialogs, widgets…) I call from the MainWindow has the MainWindow as its parent, the delete process is taken care of when I close the window using the code above. Where do I set Qt::DeleteOnClose?

What happens if I delete a pointer twice?

Thanks,

 Signature 

Joey Dumont

June 27, 2011

Lukas Geyer Lukas Geyer
Gene Splicer
2074 posts

close() won’t delete the dialog (= call the destructor) unless the WA_DeleteOnClose attribute is set. The flag can be set any time (preferebly before closing) using QWidget::setAttribute, and – of course – if your dialog is created on the heap (if it is created on the stack it will be destructed automatically when going out of scope).

However, if you set a parent for your dialog, it will be automatically deleted as soon as the parent is deleted. If you do not set a parent, it is your responsibility to delete the dialog (by either calling delete or setting the WA_DeleteOnClose attribute).

June 27, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Thanks for answers, Qt devs! I really appreciate it.

 Signature 

Joey Dumont

June 27, 2011

Lukas Geyer Lukas Geyer
Gene Splicer
2074 posts
Joey Dumont wrote:
What happens if I delete a pointer twice?

If the pointer has been set to 0 after the first deletion usually nothing, as

  1. delete 0;
is perfectly valid C++ if I remember correctly.

However, if you call delete on a non-null pointer which has already been deleted this usually leads to unexpected behaviour and will crash your application at best.

June 27, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

In that case, I’ll be careful to always declare a parent. Seems like the easiest solution.

Thanks again!

 Signature 

Joey Dumont

June 27, 2011

mlong mlong
Mad Scientist
1517 posts

In that case, I’ll be careful to always declare a parent. Seems like the easiest solution.

And, if you do ever delete anything manually, be sure to set the pointer to 0 after the call to delete. It’s a good, safe practice.

 Signature 

Senior Software Engineer
AccuWeather Enterprise Solutions
/* My views and opinions do not necessarily reflect those of my employer.  Void where prohibited. */

 
  ‹‹ problem with the trayicon , when application is closed the icon still in the tray      How to I transfer file with size more than 65KB? ››

You must log in to post a reply. Not a member yet? Register here!