Why does Qt use raw pointers? - c++

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.

Related

How should I store pointers in Qt?

My pet project has come to the point where I should start tracking pointer lifetime, and I'm trying to develop some system for it. Sadly, the popular advice to use smart pointers everywhere does not apply since Qt API itself uses naked pointers on every occasion. So, what I came up with is this:
For everything owned by Qt,
use pointers naked locally;
pass them between functions naked too;
store them as a subclassed QPointer that makes isNull() check before conversion to naked.
For everything cleanly owned by me, use smart pointers as advised. I'm going to go with the std:: versions here.
The case that bothers me. For objects that switch ownership (like widgets added/removed from a layout)
use, store, pass pointers naked;
delete them manually when appropriate.
Suggestion, comments, advice? I don't like this scheme much myself.
First, hold things by value where you can. View each use of new, make_unique and make_shared with suspicion - you must justify each dynamic object creation. If a sub-object has the same lifetime as the parent, holding by value is a no-brainer. For example:
class MyWidget : public QWidget {
Q_OBJECT
QGridLayout m_topLayout{this};
QLabel m_sign{"Hello World"};
public:
MyWidget(QWidget * parent = nullptr) : QWidget{parent} {
m_topLayout.addWidget(&m_sign, 0, 0);
}
};
You're passing pointers around, but object ownership is clear and there's no change of ownership. Just because a QObject has a parent doesn't mean that the parent "owns" it. If the child is destructed before the parent, the ownership ceases. By using C++ semantics - namely the well-defined order of member construction and destruction - you have full control over child lifetimes and no QObject parent gets to interfere.
If you have non-movable objects that have one owner, use std::unique_ptr and move it around. That's the way to pass dynamically created QObjects around your own code. You can remove them from the pointer at the point where you make their ownership managed by a QObject parent, if there is such.
If you have objects with shared ownership, where their life should end as soon as possible (vs. when the application terminates, or some long-lived object gets destroyed), use std::shared_ptr. Ensure that the pointer outlives the users. For example:
class MyData : public QAbstractItemModel { /* ... */ };
class UserWindow : public QWidget {
Q_OBJECT
std::shared_ptr<MyData> m_data; // guaranteed to outlive the view
QTreeView m_view;
public:
void setData(std::shared_ptr<MyData> && data) {
m_data = std::move(data);
m_view.setModel(m_data.data());
}
};
This example is perhaps contrived, since in Qt most users of objects watch the object's destroyed() signal and react to the objects destruction. But this makes sense if e.g. m_view was a third-party C API object handle that had no way of tracking the data object's lifetime.
If the object's ownership is shared across threads, then the use of std::shared_ptr is essential: the destroyed() signal is only usable within a single thread. By the time you get informed about object deletion in another thread, it's too late: the object has been already destroyed.
Thirdly, when you return instances of dynamically created objects from factory methods, you should return them by a naked pointer: it's clear that a factory creates an object for someone else to manage. If you need exception safety, you can return a std::unique_ptr instead.
For starter, in Rome, be Roman.
QT was developed in the very early 90's and it was a great success at a time.
unfortunately, QT didn't really adopted new features as the time went by so the API itself has very old C++ style to it (and may I say, a Java style to it?)
you can't force QT to suddenly be C++14 because it's not. use the popular-QT conventions when it comes to QT. use raw pointer if that was the platform design goal. use value types when you can't.
But I don't think you make QT work that much with C++14. stick the QT idioms as they given by the platform.

QStyle ownership

When using styles in Qt applications, I ran across an interesting problem of QStyle ownership. QStyle inherits from QObject, which typically accepts QObject* parent as a constructor parameter to manage the lifetime of its child. But QStyle's constructor does not have this constructor parameter. First question - why is that?
Moreover when setting style to the whole application with QApplication::setStyle(QStyle * style), the documentation says that the application object takes the ownership of the style. So writing (as in docs) app->setStyle(new MyWonderStyle()); should be safe and the application should delete the style when not used any more. I hope it does that.
But for QWidget::setStyle(QStyle* style) the documentation says that the ownership is not transferred. So in my view writing widget->setStyle(new MyWonderStyle()); results in memory leak if the style of the widget is set more than once or when the widget is deleted.
So my question - what is the best practice for managing custom styles especially the ownership in Qt? Is there some standard way or is it completely up to the developer to handle it?
I would say that QApplication::setStyle(QStyle*) takes ownership of QStyle because there is an overloaded function QApplication::setStyle(QString). This function creates a QStyle object internally and takes ownership of it because there is no other option in that case. Taking ownership in one function and not taking it in another one could result in confusion.
On the other hand, QWidget does not take ownership of QStyle because you may want to assign the same style to multiple QWidgets.
Lack of QStyle(QObject*) constructor is probably just an oversight. You can safely use setParent(QObject*) instead. In fact, QApplication::setStyle(QStyle*) uses setParent to take ownership of QStyle.

Smart pointers memory managers in Qt

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.

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.

Memory management for collections of widgets in Qt

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.