I'm trying to develop a Qt Application for mobile phones, so I decided not to use any standard library(as I fear some platform may not yet be supported). So, I had to reimplement the smart pointer wrapper(using the standard draft, of course) without any standard headers. In Qt, there are some Widgets, such as QMenu and QToolBar which when needed to be created -- It is created as such
QMenu *mainMenu = new QMenu;
QToolBar *toolBar = new QToolBar;
//To add a new menu bar or ToolBar, we do
mainMenu = menuBar()->addMenu("&File");
//add all the elements to the first menuBar
mainMenu->addAction(QAction { });
mainMenu = menuBar()->addMenu("&Edit"); //for second Menu
//same goes for QToolBar
The only way I implemented the unique_ptr "observers" is to use the get(), operator* and operator-> member functions to access the underlying members. What's obvious is that MenuBar()->addNew() returns a new pointer to another mainMenu.
Now to my question(s), what happens to the old pointer(s) that ? What keeps track of them? How can smart pointers be used in replacement of these naked pointers or do I have to stick with the "good old ways" of using strictly the naked pointers?
NOTE: All files can be found here
as I fear some platform may not yet be supported
That feels like incorrect guess. Every mobile platforms support it these days and Qt does depend on the standard library explicitly these days.
Even if it did not, you do not need to implement your own smart pointer as Qt has been providing these for ages:
QPointer
QSharedPointer
QWeakPointer
QScopedPointer
Here you can find a thorough explanation about them by Thiago.
So, the bottom line is just this: do not implement them yourself because you are reinventing the wheel and it is likely that you will need to fix bugs that had been fixed awhile ago. The ready-made solution will probably also scale better than your implementation from scratch and maintained by others without you needing to spend time with it.
If you only wish to deal with the automated construction and decontruction of QObject subclasses, you could also use the Qt parent/child hierarchy. Here you can read more about that one:
Object Trees & Ownership
That means, you could write something like this for QWidgets (because they are also QObjets):
QMenu *mainMenu = new QMenu(this);
QToolBar *toolBar = new QToolBar(this);
where this is basically the parent, like mainwindow, or it could be the Qt application object if you have one top-level widget, for instance, and so on.
The simplest method for managing memory with Qt is by leveraging their "object tree" structure. You can read more about it in this question: Memory management in Qt?. Basically, Qt keeps a tree of parent-child relationships between QObjects and when the parent is deleted, it deletes all child objects. So feel free to use good, old new QObject(parent) and let Qt handle the cleanup for you.
Related
I have gone back to Qt/C++ programming recently after coding a lot with plain C++.
When browsing StackOverflow, I often catch up on posts like "Why use pointers?" where in most cases the gist of the answers is "if you can avoid it, don't use them".
When coding in C++, I now mostly try using stack variables which are passed by (const) reference or, if necessary, std::shared_ptr resp. std::unique_ptr where needed.
Getting back to Qt, I found all those "principles" to be completely ignored apparently.
I know that Qt uses its own memory management to take care of raw pointers, but here's my question:
Why don't they at least use shared_ptr or unique_ptr, particularly since they even have an own implementation QSharedPointer?
Qt since versions 4.x was designed around imitating Java's framework ideology in C++ environment, using C++98 means. Instead of RAII approach of interaction it establishes "owner" - "slave" relation, in framework's term that's "parent" and "child". More of, Qt uses concept of PIMLP -private implementation. QObjects you operate with aren't real representation of what is happening, they are interfaces to completely hidden inner implementation.
By design, you have to create a QObject-derived object of child element and pass ownership to the owning object . E.g. where a window is an owner, a Button inside window will be the "slave" object. When owner is deleted, all objects that were slaved to it will be deleted too. All QObjects are thread-aware, but QWidgets can work only in main thread. This creates a non-owning pointer:
QWidget *myWidget = new QWidget(mainWindow);
mainWindow will be owning QWidget instance in this case. But this one is owning?
QWidget *myWidget = new QWidget;
It isn't. It's still owned by QApplication.
QObjectDerivedClass *myWidget = new QObjectDerivedClass;
It's an owning pointer, but this object was registered to exist in our framework. Even more, any instance can be found if it was assigned a name, storing QObjects to reach them is just an caching optimization.
All QObjects and QWidgets are registered globally and are iterable. With destruction of QApplicationCore instance all QWidgets of top level will be freed. There is undocumented exception out of that rule at least in Qt 4.x versions that QDesktopWidget objects are ignored even if they are top-level widgets. So, if a QMainWindow was forced to appear on certain screen by becoming its child, it wouldn't be destroyed.
Now comes into play signal-slot connections. In GUI certain handlers begin their work as soon as parent-child connection is established, but you can add new handlers. if a child object is deleted between beginning and end of message pump created by QEventLoop, your program may encounter an UB. To avoid it, you have to call deleteLater() which marks object for deletion at designed moment. Processing signals between threads is done separately. Practically, the main event loop is the only part of GUI that is synced with other threads.
With such complex structure and already existing requirement of working in one thread, imposed by some of supported embedded platforms, need to use smart pointers within GUi framework was negligible compared to possible impact on performance.
Before C++11 Qt had QPointer (and still got it), which is aware if QObject still exists or not using mechanics similar to owner-child interaction.
This design predates C++11 and QSharedPointer appeared only after that to fill a niche requested by users to maintain user-defined data model. It doesn't support some features, e..g you can't have an atomic version of it like ISO version does, it's only partially atomic until very last releases of 5.x. QAtomicPointer isn't either QPointer or QSharedPointer, it acts like a std::atomic<QObject*>. QSharedPointer though allows use of custom non-standalone deleter, including a call of deleteLater():
QSharedPointer<MyDataQObject> objPtr { new MyDataQObject, &QObject::deleteLater };
Assuming that MyDataQObject is derived from QObject, objPtr will call method deleteLater() in context of managed object instead of using delete on managed pointer when destroyed or reset.
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);
//...
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.
When working with Qt widgets (i.e; QLabel), why do we use pointers?
For example, why do we write:
QLabel *label = new QLabel("Hello");
And, not:
QLabel label = new QLabel("Hello");?
Thanks.
new returns a pointer. If you create an object via dynamic memory allocation - you obviously have to use a pointer.
QLabel label = new QLabel("Hello"); is incorrect code and will not compile.
Why do you use dynamic allocations for widgets? Because they have to be alive between function calls, as with any event driven GUI system. Allocations on stack (local objects) will be deallocated at the end of the scope, which wouldn't work well with widgets.
Because if you will create them on a stack they will be deleted after end of scope.
If you will write something like this:
void foo()
{
QWidget windget;
}
widget will be removed after foo() is terminated. If using new it will live until it will be deleted manually (usually by parent Widget).
I don't think QLabel label = new QLabel("Hello"); will even compile. Possibly you ment
QLabel label("Hello");
I think this is not a Qt problem, this should be a question of C++ programming.
You maybe use Java before, as java don't have pointer concept.
My suggestion, find a C++ book and learn the basic concept and usage about what's the meaning for a C++ pointer before you try to use C++ and Qt.
Just to be complete, there is no reason why you shouldn't allocate some widgets on the stack. This is especially handy for objects with a limited lifespan, like context menu's and modal dialogs where you have to wait on the result. On these widgets you normally call exec(), which blocks until the user closes it.
If you want to define a var without a pointer, it looks like QLabel label;
The label we got:
is located on the stack.
can not support polymorphism.
In c++ a var will only be object-oriented if you use it via a pointer or a reference. Qt is a object-oriented class library, so this is why QLabel is defined with a pointer.
Sorry for the dumb question, but I'm working with Qt and C++ for the first time, and working through the tutorial and some samples.
One thing that was mentioned was that Qt stuff doesn't need to be explicitly deleted. So, main question, does this also apply to collections of Qt stuff? Like say I want a dynamic number of MyWidgets, so I keep a vector or whatever of them. Are they still taken care of for me?
As a side question, what is going on to make it so I don't have to worry about destructors?
The Qt memory management model is based upon a parent-child relationship. Qt classes take an optional parent as a parameter of their constructor. The new instance registers with this parent such that it is deleted when the parent is deleted. If you are using a Qt collection (e.g. QList), I believe you can set the list as the parent of its entries. If you're using an std::vector or other collection type, you will not get "automatic" memory management.
The Qt model makes a lot of sense in a UI hierarchy where it matches one-to-one with the UI hierarchy. In other cases, it doesn't always map as cleanly and you need to evaluate whether using the Qt system makes sense for the particular situation. The normal C++ tools still work: you can use std::tr1::shared_ptr or any of the other smart pointer classes to help you manage object lifetime. Qt also includes QPointer, a guarded pointer, and the QSharedPointer/QWeakPointer pair that implement a reference-couting smart pointer and weak-reference pair.
Qt has an interesting object model for sure. When I first started it made me uneasy that there were so many new Foo calls and no deletes.
http://qt.nokia.com/doc/4.6/object.html Is a good place to start reading up on the object model.
Things of interest:
QObject subclasses have their assignment and copy-ctor methods disabled. The chain of object child-parents is maintained internally by QObject.
Generally when instantiating a QObject subclass (if you don't plan on managing its pointer yourself) you will provide another QObject pointer as the parent. This 'parent' then takes over the management of the child you just made. You can call setParent() on a QObject to change who "owns" it. There are very few methods in Qt that will change the parent of an object, and they all explicitly state that they do in the docs.
So to answer your specific question: it depends on how you made all of your MyWidget instances.
If you made each one with a parent, then no you don't have to delete them. The parent will delete them when it gets deleted.
If you're keeping a QList<MyWidget*> collection of them, and you didn't give them a parent, then you should delete them yourself.