why qt application always new widgets instead of on stack? - c++

there. I've seen this example from qt: https://doc.qt.io/qt-5/qtwidgets-widgets-calculator-example.html, and wonder why qt always create widgets with new instead of allocating on stack
Button *Calculator::createButton(const QString &text, const char *member)
{
Button *button = new Button(text);
connect(button, SIGNAL(clicked()), this, member);
return button;
}
create widget on stack is faster, and in this question: QT-specific difference of stack vs. heap attributes?
Mike's answer says that create on stack is perfectly fine, but why official documents use new mostly?

This is simple: because you want the widget to live even after this function scope is finished and QObjects are not copyable. The following code does not work because you cannot copy the object.
Button Calculator::createButton(const QString &text)
{
Button button(text); // allocated on stack, it is OK so far...
return button; // nope, you cannot copy that! it does not compile.
}
The following code does not work either because you would be passing a deleted object.
Button *Calculator::createButton(const QString &text)
{
Button button(text); // allocated on stack, it is OK so far...
return &button; // ... returning pointer, still OK...
// Oh no! End of scope here, the object gets murdered now.
// whoever holds the pointer to it, holds a dead, invalid object.
}
The object gets deleted at the end of scope and you would be passing a pointer to freed, hence invalid memory.
The example you referred to
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = nullptr);
private:
QPushButton button;
};
does not necessarily mean that the button is created on the stack. It depends on how the instance of Widget2 is created. If it is on the stack, then also button is on the stack. If it is newed on the heap, then also button is on the heap. The difference from the "normal" case where button is declared and kept as a pointer is that in the example above they are allocated together in one allocation. Yes, it is negligibly faster but it is just a premature optimization. Allocation of widgets will never ever be your bottleneck, believe me. Btw. most objects in Qt are implemented using PIMPL idiom to preserve binary compatibility, so they internally allocate their private objects on the heap anyway.
Yes, you can keep your button as a NON-pointer member. This is legal. But it is not wise. There is an issue with this approach: you must #include all the subwidgets in the header and you cannot forward-declare them. Which definitely makes you compile time longer. But that is not the main problem, you can wait a little. The bigger problem is that you are introducing building dependencies which makes your code less composable. Imagine you have your custom widgets split into multiple libraries - then everything what you #include in your headers visible to other modules also requires to be visible to these modules. This soon becomes unmanageable mess because you will not be able to hide/encapsulate implementation details. And the fact that your widget uses some button certainly is an implementation detail. Just keep as little details in your header as possible. Keeping a pointer (can be forward-declared) is definitely less of a burden than keeping a non-pointer member (must be #included!). Moreover if you keep a pointer, then you can use substitution principle and this pointer can actually point to any subclass instance. In little toy applications or school homeworks this does not matter but when you are designing a really large application wit lots of modules and submodules organized as libraries or when you are writing libraries which are to be used by others, then these things REALLY DO matter. This makes the difference between well maintainable and totally unmaintainable code.
In my practice I have encountered only two usecases where widgets are actually allocated on the stack. First is when they are created in main() where you can write:
int main() {
QApplication app;
MainWindow w; // it is really on the stack
w.show();
return app.exec();
// here is the main window automatically destroyed
}
Another case is when you open a display a modal dialog with a blocking event loop using exec().
void showSomeMessage() {
QMessageBox box; // yes, we should set a parent here, for sake of simplicity I omitted it
// etc. set text and button here
box.exec(); // blocking here, we are waiting for user interaction
// end of scope - we are done here, we do not need the message box any more
// so it is perfectly fine it gets automatically deleted here
}
These cases are perfectly fine. Actually, as you can see blocking exec() in both these cases, they are very similar.
Conclusion: it is better to declare member QObjects or QWidgets via pointers and always forward-declare them in your headers instead of #includeing their headers. This way you can design more composable, maintainable and future-proof code. You will not see any significant difference in small toy projects, but you will benefit from this good practice when your codebase grows larger. Even better habit is to keep them via QPointer (which a special Qt weak pointer), which has twofold benefit: 1) it is automatically initialized to nullptr and 2) when the objects gets destroyed, the pointer is automatically set to nullptr so you can easily check if it is alive. Plus QPointer provides implicit conversions to raw pointer so it does not affect the way you write your code. It is a very handy class.

Related

Memory-Management in Qt: AddressBook tutorial

So, I've learned so far, that Qt releases the memory of all child objects when a parent object gets deleted. Also, one generally doesn't have to care about memory management for objects created on the stack (i.e. NOT as pointers).
Now, when I did the very good "AddressBook" tutorial, I found this in part 5:
AddressBook::AddressBook(QWidget *parent) : QWidget(parent)
{
dialog = new FindDialog;
}
Complete source is available:
addressbook.h
addressbook.cpp
finddialog.h
Here, dialog is a private member of AddressBook, and it is a pointer to a FindDialog. FindDialog inherits QDialog, but no this-Pointer is passed to the constructor (as seen above). No explicit destructor exists, there is no delete dialog-call...
Also, not passing this seems to be intentional:
[The FindDialog's] constructor is defined to accept a parent QWidget, even though the dialog will be opened as a separate window.
Wouldn't this cause a memory leak? Or is there some other mechanism that will silently delete dialog and free its memory?
Thanks in advance for any help!
Update: I posted this issue to the qt-project.org forums and it should get fixed soon.
There is no excuse for this, and it eventually has more issues than you just bring up, namely:
It is not managed as you say.
It does not use the conventional new Foo() syntax.
It is not done in the constructor's initializer list.
The OS will probably free this up once the application quits, but still, I always speak up against such issues, anyhow, especially in example projects. The appropriate fix would be to use either a stack object instead of the heap object or QPointer in my opinion.
See the following post for details in case the latter:
How to crash (almost) every Qt/KDE Application and how to fix
This should be reported and fixed upstream; good catch!
I have just submitted a change to Gerrit about this in here.

Is there any way to use Qt without using dynamic memory for everything?

So, I think I've searched the web quite thoroughly about this and found nothing really useful (just confusing at most...).
I'd like to know how I can (if possible) use Qt with non-dynamic memory. The problem I face is that for many widgets, I know exactly what I want to use (these sub-widgets, these layouts, in fixed numbers, etc.). Yet, everything in Qt seems to get in the way when you don't use dynamic memory. A simple example is QLayout, which from the Qt documentation is designed to take ownership of anything it is added. So basically, the following code:
//In header
class ThumbnailDialog : public QDialog
{
Q_OBJECT
public:
ThumbnailDialog(QWidget* parent = 0);
~ThumbnailDialog(void);
private:
QPushButton m_confirm;
QPushButton m_cancel;
QHBoxLayout m_buttonsLayout;
};
//Implementation of ctor
ThumbnailDialog::ThumbnailDialog(QWidget* parent):
QDialog(parent)
{
//...
m_buttonsLayout.addWidget(&m_confirm);
m_buttonsLayout.addWidget(&m_cancel);
//...
setLayout(&m_dialogLayout);
}
...will end up (on MSVC) in a debug assertion fail for _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) because, in the ThumbnailDialog's dtor, the layout tries to delete the buttons... which it obviously shouldn't.
So, am I forced to use dynamic memories everywhere, as this "Qt Expert" advocates (while mentioning "heap", though...) ? This seems wrong as this prevents taking advantage of RAII (if parent-child relation means there'll be a delete, one can't use smart pointers to do that I suppose, then). It also feels terribly wrong to resort to dynamic memory for things known at compile-time... (but I could be wrong, that's just my feeling).
So: is there any way of using Qt without resorting to dynamic memory and news for every single widget/layout ?
I think you are misunderstanding the problem here. You are not double deleting something, you are deleting an object allocated on the stack:
int foo = 12345;
int* pFoo = &foo;
delete pFoo;
This is what happens when you pass a pointer to a stack based object to QHBoxLayout, hence your heap corruption debug assert.
Qt manages QObjects this way because most GUI's have LOTS of widgets, which makes managing GUI object life times easier, it also allows queued deletes across threads etc. Also internally most classes use PIMPL's so you are not avoiding the heap/dynamic allocation even if your code worked.
Having said all this you can get it to work without the heap alloc if you wish, but it is far more effort than its worth. In your example you would have to remove the widgets from the layout in the destructor, but be sure the nullptr check things in case the ctor has thrown, if they're not in the layout when its destructor is hit then it won't be able to delete them.
One more thing to think about.. if Qt was designed to work this way then you could easily end up in the situation where you overflow the stack on some platforms. E.g Qt works on Symbian/S60 which has extremely limited stack, running your code there could easily cause a stackoverflow :).
Yes, there is. (and in a pretty clean way, I believe)
You just have to be aware about the order of destruction of your QObject hierarchy:
As explained in the Qt docs, a lot of objects claim ownership of their children and therefore want to make sure they get cleaned up when they die.
QObject’s dtor relieves its parent of that ownership.
Destruction of non-static data members happens from bottom to top.
Which means that, in your case, you just have to move the layout to the top:
private:
QHBoxLayout m_buttonsLayout;
QPushButton m_confirm;
QPushButton m_cancel;
All the layout’s children’s dtors unregister themselves from the layout, so when the layout destruction happens there are no registered childs left.
Previously the layout’s destruction deleted the children which where not newd in the first place.
This may seem tedious at first sight, but in practice the hierarchy within a custom widget is pretty flat. The order of widgets in one layer of the hierarchy – in this case the QPushButtons – is not important which usually means that you only have to arrange the layouts on top properly.
The problem you're seeing is that you're not thinking about what is happening. The QPushButton instances in the class are created and owned by the class. When the class is deleted, it will call the destructor on the QPushButtons.
Qt provides useful parenting of objects and deleting a parent will handle deletion of all its child objects.
So, in the case of your example, you have two things that are going to call the destructor on the QPushButtons: 1) The deletion of the class object for ThumbnailDialog and 2) The deletion of the buttonlayout, which will try to delete its children and will fail, as the object is on the stack.
What you can do, if you really want, is ensure that the QPushButton items are removed from the button layout, in the destructor of ThumbnailDialog by calling removeWidget() on the button layout.
However, this is messy. Dynamic allocation is a much better method, as it allocates objects on the heap and not the stack.
Also note, with Qt's parenting, it means that you can create a lot of widgets without needing to keep track of them. For example, you can do this: -
ThumbnailDialog::ThumbnailDialog(QWidget* parent):
QDialog(parent)
{
//...
m_buttonsLayout.addWidget(new QPushButton("Confirm"));
m_buttonsLayout.addWidget(new QPushButton("Cancel"));
//...
setLayout(&m_dialogLayout);
}
In this case, the push buttons don't even need to be defined in the header and you can be assured that they'll be deleted along with their parent.
No, not really. I'm afraid. Qt relies on this stuff.
If you have read the other answers and you still want to use static allocation, you can release the ownership that was taken when doing addWidget():
//...
m_buttonsLayout.addWidget(&m_confirm);
m_buttonsLayout.addWidget(&m_cancel);
// release the ownership by setting no parent
m_confirm.setParent(0);
m_cancel.setParent(0);
//...

C++ - Why do I create these widgets on the heap?

When creating a GUI with C++ and Qt you can create a label for example like this :
QLabel* label = new QLabel("Hey you!", centralWidgetParent);
This creates the object on the heap and will stay there until I either delete it manually or the parent gets destroyed. My question now is why do I need a pointer for that? Why not create it on the stack?
//Create a member variable of Class MainWindow
QLabel label;
//Set parent to show it and give a text so the user can see it
QWidget* centralWidget = new QWidget(this); //Needed to add widgets to the window
this->setCentralWidget( centralWidget );
label.setParent(centralWidget);
label.setText( "Haha" );
This works fine, I can see the label and it did not vanish.
We use pointers in C++ to let something live longer so we can use an object in various scopes. But when I create a member variable, won't it stay until the object gets destroyed?
Edit:
Maybe I didn't clarify it enough. This is the MainWindow class:
class MainWindow : public QMainWindow
{
Q_OBJECT
QLabel label; //First introduced here...
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
//Constructor
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget* centralWidget = new QWidget(this);
this->setCentralWidget( centralWidget );
label.setParent(centralWidget);
label.setText( "Haha" );
}
If your label gets out of the scope, the destructor (QLabel::~QLabel) will be called. From the docs:
Destroys the object, deleting all its child objects.
It is not necessary to create object on the heap - you could put the object on the stack, but then you need to be responsible about lifetime of the object (the one of the most problematic issues about allocating data on the heap is the question of "who and when should delete these objects?", and in Qt it is handled by the hierarchy - whenever you delete your widget, all the child widgets will be deleted).
Why your program works - I don't know - it may just not work (label is destroyed at the end of the scope). Another issue is - how will you change the text of the label (from some slot, for example) if you don't have a reference to it?
Edit I just saw that your label is a member of the MainWindow. It is perfectly fine to have a complete objects, and not the pointer to the objects as the member of your class, as it will not be destroyed before MainWindow is. Please note that if you create instance of your MainWindow like this:
MainWindow *w = new MainWindow();
label will be created on the heap.
Because that is how Qt was designed. I realize that's not a very satisfying answer, but Qt was simply designed as "widgets are created on the heap, and parents are responsible for deleting their children".
Realize that the origins of Qt are old, older than what we consider "modern C++".
Another thing to keep in mind is that Qt uses the so called pimpl paradigm where object data is implicitly shared and managed behind the class you actually instantiate. See here: http://qt-project.org/wiki/Dpointer
The bottom line is that if you are allocating on the stack in order to avoid using the heap, Qt is just pulling a fast one on you and using the heap anyway.
Allocating a widget as a local variable typically is not a good idea, since usually it will go out of scope before being useful in any way; since QObject supports the composition pattern via its "parent-child" relationships (that are well integrated with C++ destructors), usually the simplest thing is just to exploit such a feature.
On the other hand, you can make it a member of your MainWindow class, or in general allocate it in any way such that it has a lifetime less than the lifetime of its parent. In facts, when such QLabel is destroyed, it automatically deregisters from its parent, avoiding double deallocation. But often is more comfortable just to allocate the widgets on the heap, registering them as children of the current window, since usually you don't actually need to access many widgets after you created them (e.g. labels), so it's not necessary to clutter your class with useless data members. You just do new QLabel(this, ...) into your window constructor and that's it.
What you should not do, instead, is to allocate your widgets without new if their lifetime gets longer than the lifetime of their parent (e.g. putting them in a global or static variable) - doing this will cause the parent to try to delete them on its destruction, which will cause a crash at best, silent memory corruption at worst. This can be fixed (by manually deregistering the widgets in your class destructor), but I can't imagine any scenario where such a thing would be useful.
Main reason - possibility of dynamic creating / removing widgets. QObject (and QWidget) desing as classes that could not have copy constructor, so you couldn't pass is in arguments (by value/reference). So using pointers in all cases makes code more simple and clear.

Difference between using a pointer and a class for creating a modeless window in MFC

This resource describes a method of creating a modeless dialog using pointers. They create a pointer that pointer to the dialog class and then use the -> syntax.
CModeLess *m_pmodeless = new CModeLess(this);
m_pmodeless->Create(CModeLess::IDD);
m_pmodeless->ShowWindow(SW_SHOW);
I have been doing something like this so far:
CModeLess m_pmodeless;
m_pmodeless.Create(IDD_DIALOG);
m_pmodeless.ShowWindow(SW_SHOW);
I do this mainly because I feel comfortable using classes. Is there any disadvantage of using this approach?
Secondly, in the pointer approach I have to do something like this to close the window: (if I am not mistaken)
if(m_pmodeless != NULL) { delete m_pmodeless; }
Is there some deletion I have to do If I use classes or is m_pmodeless.closeWindow() enough?
I apologize if this is a very basic question, but i'm curious to know.
This is a tricky question to answer, as a lot depends on exactly what you are trying to do and also on exactly how CModeless is implemented. In general you are right to avoid pointers, but GUI programming has special issues because the C++ objects in your program represent GUI objects on the screen, and coordinating the destruction of the C++ objects in your program with the GUI objects on the screen can be quite tricky. Sometimes pointers are the simplest answer to this problem.
I'm assuming that m_pmodeless is a member variable of another class.
One issue is the lifetime of the objects. In the class version the CModeless object will be destroyed when the containing object is destroyed. Whether that's OK for you depends on your code. Whether that also destroys the modeless dialog depends on how CModeless is implemented. You need to look at the CModeless destructor if you can, or the documentation for CModeless if you can't. With the pointer version you have explicit control over when the object is destroyed, just call delete at the right time.
Another issue is that some GUI libraries automatically delete the C++ object when the GUI object is destroyed. Something like this (on Windows)
case WM_NCDESTROY:
...
// last message received so delete the object
delete this;
break;
Code like this is assuming that all your objects are heap allocated and automatically deleting them for you at the right time. If CModeless is written like this then you have no choice but to use the pointer version.

Confusion about usage of 'new' for UI Widgets in QMainWindow constructor

My coding practice using Qt can best be described as follows:
If the Widget is going to be actively used (e.g. A QLineEdit which provides text), I declare it in the header file and then initialise it in MainWindow.cpp.
e.g. TextEditor.h:
class TextEditor
{
//other code
private:
QLineEdit edtFind;
};
2.. If a widget is not going to be used (e.g. QLabel, QWidget), or it's part of a signal slot system (e.g. QPushButton), I declare and inialise it inside constructor using new.
-e.g.
TextEditor::TextEditor()
{
//other code
QWidget* searchPanel = new QWidget();
edtFind = new QLineEdit("Enter Search Term");
QPushButton* findButton = new QPushButton("Find");
connect(findButton,SIGNAL(pressed()),this,SLOT(find()));
ui->statusbar->addPermanentWidget(searchPanel);
}
My question is, am I using an efficient approach in point 2? Would it be better to not allocate memory from the heap?
Thanks.
Your approach is not efficient. You should use heap allocated objects when you actually need them:
objects that have a longer lifetime
using a forward declaration in order to avoid including a header file
holding a reference to an object created elsewhere
Your approach is more complicated without any visible benefit. Heap is known to be slow, and allocating a large number of small objects is known to fragment it (this might not make a difference in your app but it's still a bad practice).
While good advise for C++ in general, answer 1 is actually wrong for a big part in Qt: QObject (and with it all widgets, since QWidget derives from QObject). Rule there is to always allocate QObjects on the heap if they have a parent, because QObject features a parent-based garbage collection (when the topmost QObject-parent gets deleted, it will ask all its children to delete themselves recursively). The application may try to delete an object on the stack, which leads to a crash.
Note that some operations in Qt implicitly add or change the parent of a QObject as a side-effect (reparenting), such as adding a widget to a layout. However, this is usually documented in the API documentation. Since reparenting is very common with QWidgets, you should never put them on the stack. Other QObject-derived classes are safer, consult the API documentation in case of doubt.