Why don't the official Qt examples and tutorials use smart pointers?
Why do official examples and tutorials about the Qt library never make use of smart pointers? I only see new
and delete
for creating and destroying the widgets.
I searched for the rationale but I could not find it, and I don't see one myself except if it's for historic reasons or backward compatibility: not everyone wants the program to terminate if a widget constructor fails, and handling it via try/catch blocks is just ugly (even if used in few places). The fact the parent widgets may take the ownership of the children also only partially explains the thing to me, as you would still have to use delete
for the parents at some level.
Because Qt relies on a parent-child model to manage Qobject resources. It follows the composite + Chain-of-responsibility pattern, which is used from event management to memory management, drawing, file handling, etc...
Actually, trying to use a QObject in a shared\unique pointer is overengineering (99% of the time).
- You have to supply a custom deleter which will call deleteLater
- Your qobject with parents already have a reference in the parent object. So you know that a object is not leaked as long as the parent exist. When you need to get rid of it, you can call
deleteLater
directly. - Your QWidget without parent already have a reference in the Qapplication object. So same as point 2.
That said, you can still use RAII with Qt. For instance QPointer behaves as a weak reference on a QObject
. I would use QPointer<QWidget>
rather than QWidget*
.
note: to not sound too fanboy, two words : Qt + valgrind.
Smart pointers to children
The smart pointer classes std::unique_ptr
and std::shared_ptr
are for memory management. Having such a smart pointer means, that you own the pointer. However, when creating a QObject
or a derived type with a QObject
parent, the ownership (the responsibility to clean up) is handed over to the parent QObject
. In that case, the standard library smart pointers are unnecessary, or even dangerous, since they can potentially cause a double deletion. Yikes!
Raw pointers to orphans
However, when a QObject
(or derived type) is created on the heap without a parent QObject
things are very different. In that case you should not just hold a raw pointer, but a smart pointer, preferably a std::unique_ptr
to the object. That way you gain resource safety. If you later hand the object ownership to a parent QObject
you can use std::unique_ptr<T>::release()
, like so:
auto obj = std::make_unique<MyObject>();
// ... do some stuff that might throw ...
QObject parentObject;
obj->setParent( &parentObject );
obj.release();
If the stuff you do before giving your orphan a parent throws an exception, then you would have a memory leak, if you used raw pointer to hold the object. But the code above is save against such a leak.
On a more general note
It is not modern C++ advice to avoid raw pointers all together, but to avoid owning raw pointers. I might add another modern C++ advice: Don't use smart pointers for objects that are owned by some other program entity.
You already answered your own question : except if it's for historic reasons/backward compatibility
. A library that's as huge as QT can't assume that everyone using the library has compilers that support C++11. new
and delete
are guaranteed to exist in earlier standards.
However, if you do have the support to use smart pointers I would encourage to use them over raw pointers.