Usually, when writing C++ code, I would hold objects always as normal attributes, thus utilizing RAII. In QT, however, the responsibility for deleting objects can lie within the destructor of QObject. So, let's say we define some specific widget, then we have two possibilities:
1) use QT's system
class Widget1 : QWidget
{
Q_OBJECT
public:
Widget1(QWidget* parent = nullptr);
private:
QPushButton* myButton; // create it with "new QPushButton(this);"
};
2) use RAII
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = nullptr);
private:
QPushButton button; // normal RAII
};
Usually, I use the first method. It seems that something could work better if a parent knows its children not only by layout. But thinking about it... The real reason for this is not quite clear to me.
I know that the stack is limited. But let's say that this does not play a role here. After all, the stack is not that small.
It seems that something could work better if a parent knows its children not only by layout.
You are right. A QObject's parent is not only used for memory management purposes, this answer sums some of its other usages. The most important ones here are the ones of QWidget's (since you are concerned about adding member QWidget's), so if you use the second approach the way you are writing it, here are some of the issues you might get:
Suppose you are instantiating Widget1 and displaying it in your main function like this:
Widget1 w;
w.show();
This will display an empty widget without the button inside it. As opposed to the behavior when button is a child of the Widget1 object, where calling show() displays the widget parent with all of its children inside.
Similar issue happens when using setEnabled(), setLayoutDirection(), ...
button.pos() won't return coordinates relative to Widget1, in fact the button is not even displayed inside it. Same issue when using move().
The event system might not work as expected. So, if the member widget does not handle some mouse/keyboard event, the event won't propagate to the parent widget (since there is no parent specified).
But the second approach can be written to utilize the parent relationship with RAII, so that above issues are avoided:
class Widget2 : public QWidget
{
public:
explicit Widget2(QWidget* parent = nullptr):QWidget(parent){}
private:
QPushButton button{this}; //C++11 member initializer list
};
Or, in pre-C++11:
class Widget2 : public QWidget
{
public:
//initialize button in constructor, button's parent is set to this
explicit Widget2(QWidget* parent = Q_NULLPTR):QWidget(parent), button(this){}
private:
QPushButton button;
};
This way there aren't any differences to the Qt Framework between both approaches. In fact, using the second approach avoids dynamic allocation when unnecessary (Note that, this might have slightly better performance, if the allocation is executed very frequently in some nested loop for example. But, for most applications, performance is not really an issue here). So, you might be writing your widgets like this:
class Widget : public QWidget
{
public:
explicit Widget(QWidget* parent = nullptr):QWidget(parent){
//add widgets to the layout
layout.addWidget(&button);
layout.addWidget(&lineEdit);
layout.addWidget(&label);
}
~Widget(){}
private:
//widget's layout as a child (this will set the layout on the widget)
QVBoxLayout layout{this};
//ui items, no need to set the parent here
//since this is done automatically in QLayout::addWidget calls in the constructor
QPushButton button{"click here"};
QLineEdit lineEdit;
QLabel label{"this is a sample widget"};
};
This is perfectly fine, one might say that those child widgets/objects will be destroyed twice, first when they are out of scope and a second time when their parent is destroyed, making the approach unsafe. This is not an issue as once a child object is destroyed it removes itself from its parent's children list, see docs. So, each object will be destroyed exactly once.
First of all you are asking about basics of C++ object oriented programing.
Standard rules of object destruction applies.
Secondly you are wrong. Stack here is not involved. You widget is placed as a class field so widget became part of your class. I will be located on stack only if you instantiate Widget1 on stack.
Size of stack doesn't matter here. Qt uses d-pointer code pattern in all QObjects. This means that Qt classes have usually small constant size (I didn't check but most probably on 32 bit systems it will be 8 bytes: pointer to virtual table and d-pointer).
Even if you instantiate object of your class on stack data alignment done by compiler can reduce difference of stack memory usage for both cases to zero (size of classes is usually rounded up by compiler to paragraph size - 16 bytes), so in your example there no reason to worry about that.
If you place a button as a part of your Widget1 there is no big difference from you application logic point of view (you've wrote "parent knows its children not only by layout" this means that Widget1 is always a parent to button).
You should use pattern with a pointer to keep code clean.
In well maintained project it is important to keep header files as clean as possible. This means that you should use forward declaration and avoid unnecessary includes in header file, for example:
#include <QWidget.h> // inheriting from this class os this include is needed
QT_FORWARD_DECLARE_CLASS(QPushButton) // don't have to include "QPushButton.h" in this header file
class Widget1 : QWidget
{
Q_OBJECT
public:
Widget1(QWidget* parent = nullptr);
private:
QPushButton* myButton;
};
Forward declarations are used big projects since it reduces a building time. If project is big this can be very important.
If you would use widget as a direct value you have include its header file "QPushButton.h".
Related
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.
Can someone explain the following please?
Stack or Heap?
In general, a QObject without a parent should be created on the stack or defined as an subobject of another class. A QObject with a parent should not be on the stack because then it might get deleted twice accidentally. All QObjects created on the heap should either have a parent, or be managed somehow by another object.
Source: LINK
Sorry, downvoting the accepted answer. Both versions as currently explained are wrong, and especially the conclusion is very wrong.
Parent/child for memory management
Amongst other things, Qt uses the parent/child concept to manage memory. When an object is parented to another one, then
deleting the parent will also delete (via operator delete) all of its children. Of course, this works recursively;
deleting a child will un-parent it, so that the parent will not attempt a double deletion. deleteLater is not required for this to work -- any deletion will un-parent it.
This allows you to build a tree of QObjects via repeated dynamic allocations through operator new, and not having the problem of having to manually delete all the allocated objects. Just give them parents, and you'll only have to delete the root of the tree. You can also delete a child (i.e. a subtree) at any time, and that will do the right thing™.
In the end, you will have no leaks and no double deletions.
This is why in constructors you'll see things like:
class MyWidget : public QWidget // a QObject subclass
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
// default destructor is fine!
private:
// raw pointers:
// we won't own these objects through these pointers.
// we just need them to access the pointees
QTimer *m_timer;
QPushButton *m_button;
};
void MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
// don't need to save the pointer to this child. because reasons
auto lineEdit = new QLineEdit(this);
auto validator = new QIntValidator(lineEdit); // a nephew
// but let's save the pointers to these children
m_timer = new QTimer(this);
m_button = new QPushButton(this);
// ...
}
The default destructor will properly delete the entire tree, although we allocated the children objects through calls to operator new, and we didn't even bother to save in members the pointers to some children.
QObjects on the stack
You are allowed (and in certain contexts it's actually a good idea) to give parents to objects allocated on the stack.
The typical example is of QDialog subclasses:
void MyWidget::showOptionsDialog()
{
// OptionsDialog is a QDialog subclass;
// create an instance as a child of "this" object
OptionsDialog d(this);
// exec the dialog (i.e. show it as a modal dialog)
conts auto result = d.exec();
if (result == QDialog::Accept) {
// apply the options
}
// d gets destroyed here
// => it will remove itself as a child of this
}
The purpose of passing this as the dialog's parent is to allow the dialog to be centered upon the parent's widget, share the task tray entry, and be modal against it. This is explained in QDialog docs. Also, ultimately, d does only need to live in that function, so it's a good idea to declare it as an automatic variable (i.e. allocated on the stack).
There you go: you've got a QObject, allocated on the stack, with a parent.
So what's the danger of QObjects on the stack? Consider this code:
QObject *parent = new QObject;
QObject child(parent);
delete parent;
As explained before, parent here will attempt to call operator delete on child, an object which was not allocated using new (it's on the stack). That's illegal (and a likely crash).
Obviously, nobody writes code like this, but consider the dialog example above again. What if, during the call d.exec(), we manage somehow to delete this, that is, the dialog's parent? That could happen for a variety of reasons very, very difficult to track down -- for instance, data arrives on a socket which causes widgets in your UI to change, creating some and destroying others. Ultimately, you would delete a stack variable, crashing (and having an extremely hard time trying to reproduce the crash).
Hence the suggestion to avoid creating code like that in the first place. It's not illegal, it may work, but it may also not work, and nobody likes fragile code.
I have recently began working with the Qt framework and realized there may be a bit about the syntax of C++ that I do not quite understand. Take for example this code that is given as a foundation when starting a Widget project in Qt.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
Where the class MainWindow is defined as:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
Class declaration
Stepping through this, I can see that a new namespace, Ui, is created. I imagine this to be an implementation effort to avoid naming conflicts with other user-implemented classes.
A new class definition follows; it inherits QMainWindow, so we are essentially creating a custom window object.
Q_OBJECT is apparently a macro that allows the user to use signals and slots in the class definitions, but I am not too worried about that code right now.
We define the constructor to be explicit thereby disallowing any implicit conversions of this class type. There is also a destructor shown.
In the private accesses, we look to the Ui namespace and create a MainWindow pointer.
Class definition
We are using an initialization list I see, but I get lost here. I see that we have a default parameter of NULL ( or 0 ) for the parent of this widget, but if a class inherents another class why must you explicitly call the constructor for said inherited class? That is:
class A {
}
class B : public A {
}
B testObject;
Does this not automatically allocate memory on the stack sufficient memory to contain both classes A and B? Why does the Qt code shown above call the constructor for an inherited class within its own constructor?
Continuing to the second parameter of the initialization list, I must say that I am confused on the syntax used here. Why do we have a pointer to a QMainWindow that we initialize by calling QMainWindow's constructor with a further call to new thereby creating an instance of itself? This initialization method seems circular.
We then call a setupUi function and pass this object for initialization.
And finally, in the destructor we simply deallocate the memory associated with the MainWindow.
As a final question, if an additional object is created, say a QPushButton, does the software automatically deallocate the memory assocated with these objects or must that be included in the destructor alongside delete ui? I have not seen a tutorial that actually does this, so I am not sure if the framework is designed such that it is handled for you.
I know there are few direct questions here, but is there any flaw in my logic for each statement?
tl;dr, skip to the first and second bullet under Class definition.
Please note that you should not ask so many sub-questions in a question, but I will try to answer your questions regardless ...
Does this not automatically allocate memory on the stack sufficient memory to contain both classes A and B?
It allocates memory for the base class, yes.
Why does the Qt code shown above call the constructor for an inherited class within its own constructor?
Because that is how C++ inheritance works. You need to initialize the base class explicitly in cases like this It could be implicit in an ideal with default constructors, but you are not even using that in here which is good.
Why do we have a pointer to a QMainWindow that we initialize by calling QMainWindow's constructor with a further call to new thereby creating an instance of itself? This initialization method seems circular.
As you explained in the beginning, you have two separate MainWindows, one generated by the Qt Designer, and one class implementation in your code, thus the namespaces you mentioned.
As a final question, if an additional object is created, say a QPushButton, does the software automatically deallocate the memory assocated with these objects or must that be included in the destructor alongside delete ui? I have not seen a tutorial that actually does this, so I am not sure if the framework is designed such that it is handled for you.
If you allocate it on the stack, it is not necessary since it will be destroyed automatically when running out of scope. If you allocate that on the heap, in the Qt world, you specify the parent as the argument for the constructor so that it gets deleted automatically when the parent gets deleted. This is done transparently for you by the Qt parent-child hierarchy and mechanism. That is why you do not see explicit delete usually in examples.
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.
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.