[SOLVED] How does Qt handle dynamically allocated objects?
-
I would like to know how Qt manages objects that are allocated dynamically. For instance, I have the following function called by a slot when a user pushes a button:
@
void maybeSave(){
if(!checkShadowCopy()){
QMessageBox *theMsg=new QMessageBox(this);
theMsg->setWindowTitle("Warning");
theMsg->setText("Do you want to save your settings before changing groups? (else changes will be lost)");
theMsg->setStandardButtons(QMessageBox::Yes|QMessageBox::No);
int res=theMsg->exec();
if(res==QMessageBox::Yes){
theGrp=lastIndex;
saveChanges();
}
}
}
@Do I need to call the destructor or will Qt take care of it. Would it be better to make the QMessageBox pointer a member of the class and allocate it in the constructor only?
-
I have the following slot which declares a QMessageBox, configures it and finally calls its exec. Since the QMessageBox is always the same, will the compiler optimize the code to do things once?
@ void on_pbIRIG_B_ClrFaults_clicked(){
QMessageBox clrMsg; clrMsg.setStandardButtons(QMessageBox::Yes|QMessageBox::No); clrMsg.setWindowTitle("IRIG-B"); clrMsg.setText("Are you sure you want to clear the IRIG-B faults?"); int res=clrMsg.exec(); if(res==QMessageBox::Yes){ pFPSengine->TduCmd.Cmd=IRIG_B_CLR_FAULTS; pFPSengine->putData(SEND_TDU_COMMAND,0); } }
@
-
bq. Do I need to call the destructor or will Qt take care of it. Would it be better to make the QMessageBox pointer a member of the class and allocate it in the constructor only?
In your first example, Qt will handle cleaning up any instance(s) of the QMessageBox that exist when the parent's destructor is called. However, if you call maybeSave() multiple times then there will exist multiple copies of the QMessageBox until such time as they are all destroyed at once.
You have various options:
You could leave it as it is, and live with multiple instances of the box hanging around (not recommended.)
You could manually delete theMsg after you're done with it.
You could make it a member variable and allocate it once (either in the constructor, or upon first use.)
As in your other code sample, you could create the QMessageBox on the stack and let it clean itself up when it goes out of scope.
(There are other options, probably, too, but these were the ones I could think of quickly.)
I'm not sure about the compiler optimizations, but since the second example is created on the stack, I would guess that it is not optimized down to do things once.
-
Ok thanks, I was hoping some sort of garbage collector would take care of it and since I don't need to destroy my UI's I guess I'm leaking.
bq. 3. You could make it a member variable and allocate it once (either in the constructor, or upon first use.)
wouldn't it be nice if this was done automatically, that way my code would be visible in the area where it is used but still have the result/efficiency of putting it in the constructor. By putting all of them in the constructor it makes the code harder to read.
bq. 4. As in your other code sample, you could create the QMessageBox on the stack and let it clean itself up when it goes out of scope.
unfortunately this approach has a drawback, I need to specify a parent or else there is a focus bug generated when I close the QMessageBox by clicking enter and without having focus on message box. ex: user is editing fields in a main form then suddenly a QMessageBox pops up. The user simply presses enter, then the user cannot edit fields on the form without focusing out to another window then back (alt+tab,alt+tab works) . This is happening one of my computers (Qt 4.6 64bits on ubuntu 10.04 64bits )
Thanks for the info
-
bq. wouldn’t it be nice if this was done automatically, that way my code would be visible in the area where it is used but still have the result/efficiency of putting it in the constructor. By putting all of them in the constructor it makes the code harder to read.
You don't have to do it all in the constructor.
In your header file:
@
private:
QMessageBox *theMsg;
@In your constructor:
@
theMsg = 0;
@And at first use:
@
void maybeSave(){
if(!checkShadowCopy()){
if (!theMsg) // Allocate the message box if it doesn't exist. Will be cleaned up by parent.
{
theMsg = new QMessageBox(this);theMsg->setWindowTitle("Warning"); theMsg->setText("Do you want to save your settings before changing groups? (else changes will be lost)"); theMsg->setStandardButtons(QMessageBox::Yes|QMessageBox::No); } int res = theMsg->exec(); if (res == QMessageBox::Yes) { theGrp=lastIndex; saveChanges(); } }
}
@ -
You can do some kind of garbage collection using one of Qt's "smart pointers":http://labs.qt.nokia.com/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/, e.g. QScopedPointer or QSharedPointer.
Keep in mind that Qt is still built on top of C++ and therefore has no influence on code generation and optimization.
-
bq. You don’t have to do it all in the constructor.
of course your right, I should of given it a little more thought.
...
@Lukas Geyer: thx for the info