PDA

View Full Version : Could I manage the resource of Qt without try and catch?



stereoMatching
8th April 2012, 09:31
class Wizard : public QDialog
{
Q_OBJECT

public:
Wizard(QWidget *parent);

private slots:
void what_ever();

private:
QPushButton *what_ever;
};

Wizard::Wizard( QWidget *parent ) : QDialog(parent)
{
QGridLayout *layout = new QGridLayout( this );

QScopedPointer<QTextEdit> textEdit(new QTextEdit);
layout->addWidget( textEdit.take(), 0, 0, 1, 2 );

what_ever = new QPushButton("whatever");
layout->addWidget(what_ever, 0, 1, 1, 1);

connect(what_ever, SIGNAL(clicked()), this, SLOT(what_ever()));
}

void Wizard::what_ever()
{
//blah blah blah
}


I have some problems about the codes.

1 : What if textEdit throw exception?
If "textEdit" throw exception, that means the
destructor of Wizard would not be called,
What would Qt handle the resource of "layout"?

2 : Could I initialize "what_ever" like this?
layout->addWidget(what_ever = new QPushButton("whatever"), 0, 1, 1, 1);
Is this safe in Qt4(4.8)?Would it have any change to cause memory leak?

Thanks a lot

wayfaerer
8th April 2012, 16:52
Qt doesn't really do exceptions. I think that your slot "what_ever" should be able to check whether or not the textEdit is valid.

I don't think you can initialize the push button like that. For your situation this appears to be the best way:



layout->addWidget(new QPushButton("whatever", this), 0, 1, 1, 1);


or



QPushButton *button = new QPushButton("whatever", this);
layout->addWidget(button, 0, 1, 1, 1);


When you pass QPushButton the "this" pointer, it ensures that the QPushButton will be deleted whenever QDialog is deleted. That's how the parenting system works in Qt... it is quite convenient!

Zlatomir
8th April 2012, 21:02
Qt itself uses error codes, so textedit won't throw any exceptions, but you can check this page for exception safety (http://doc-snapshot.qt-project.org/4.8/exceptionsafety.html) //for std::bad_alloc or other exception that can come from your "environment"

But i don't understand why do you use QScopedPointer and than take the allocated memory?

stereoMatching
9th April 2012, 05:48
Thanks, looks like I only have to handle std::bad_alloc in most of the cases.


But i don't understand why do you use QScopedPointer and than take the allocated memory?
My habit when programming without Qt(use objects to manage resources), but in Qt maybe I should just hand it to
parent rather than smart pointer?

Zlatomir
9th April 2012, 07:59
My habit when programming without Qt(use objects to manage resources), but in Qt maybe I should just hand it to
parent rather than smart pointer?
The take (http://qt-project.org/doc/qt-4.8/qscopedpointer.html#take) member function takes the ownership of the allocated memory (so the smart pointer does nothing - you just construct it then take it's allocated memory and make the QScopedPointer null), if it it would do it's job it will delete your QTextEdit at the end of your constructor, so your QTextEdit couldn't be used.

//i'm not saying that it is a bad thing to use smart pointers, but you need to be careful not to construct the smart pointer when you don't actually use their power.

stereoMatching
9th April 2012, 12:08
so the smart pointer does nothing - you just construct it then take it's allocated memory and make the QScopedPointer null
you are right, I did something meaningless, after all the resource will hand over to the parent.


I don't think you can initialize the push button like that.
Could you explain why?Because the error may occur before the button become
the child of the parent?

Thanks a lot

ChrisW67
9th April 2012, 22:58
2 : Could I initialize "what_ever" like this?
layout->addWidget(what_ever = new QPushButton("whatever"), 0, 1, 1, 1);
Is this safe in Qt4(4.8)?Would it have any change to cause memory leak?

I don't see why not, but I also don't see what you gain by doing so. If the new call fails with bad_alloc then you are in the same situation: an unhandled exception will terminate the program.

Layouts do not own their content. They do ensure that their content is parented to the widget they are applied to... if there is one. With your code: if layout has been applied to a widget then adding the push button to the layout will give it a parent and the memory is owned by the widget. If the layout has not yet been applied to a widget then the QPushButton does not have a parent QWidget and the standard Qt ownership mechanism cannot clean up the push button. So, depending on circumstances you could leak the QPushButton memory between this call and when the layout is applied to a widget.

The idiomatic:


what_ever = new QPushButton("whatever", this); // widget is owned by "this" (usually another widget)
layout->addWidget(what_ever, 0, 1, 1, 1);

ensures that the new widget is at all times owned regardless of the state of the layout.

stereoMatching
13th April 2012, 15:35
I don't see why not, but I also don't see what you gain by doing so
Because I want to make the codes become shorter
personal coding style, I like that kind of codes better
I think this is acceptable?At least this is not as complicated as


std::v.erase(std::remove_if(std::find_if(std::begi n(v), std::end(v), std::bind//blah blah blah) ) );




Layouts do not own their content. They do ensure that their content is parented to the widget they are applied to... if there is one

That means if I already assign a parent to the layout like this


QGridLayout *layout = new QGridLayout( this );
layout->addWidget(mbutton = new QPushButton("mm"), 0, 0);

it would be save even I don't declare the parent of QPushButton because the layout
would make "this" as the parent of the mButton?

wysota
13th April 2012, 15:47
Because I want to make the codes become shorter
personal coding style, I like that kind of codes better
You can make your code even shorter by removing all newline characters and you can also make all your identifiers single or double letter only.