An important rule of thumb for good coding practices is
every
new
must be matched by adelete
discussed in this previous question. Usually, we encapsulate this rule in an RAII class like std::unique_ptr
. However, Qt appears to break this pattern. For example, to create a QTimer
, a user may do something like this:
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
timer->start(1000);
The above example is found here. The QTimer
constructor is passed the this
pointer, which becomes the parent of timer
. It seems that Qt then sets up *this
to destruct QTimer
when the destructor for *this
is called. In effect, there is no need to call delete timer
.
delete timer;
anyway, such as in the destructor of a unique_ptr
? Will that call the destructor twice?timer
was allocated on the stack? Does *this
know that?Can I call delete timer anyway
If you explicitly call delete timer
, the QTimer's destructor (well, to be exact, the destructor of the QTimer's QObject base-class) will remove the QTimer from its parent-object's children-list, so that later on when the parent-object's own destructor is called, the QTimer will not be deleted a second time. So that's okay.
such as in the destructor of a unique_ptr
With unique_ptr
(or shared_ptr
), OTOH, you will run into a problem -- while the QObject classes are smart enough to update their parent-QObject when they are destroyed, they do not know how to update a unique_ptr
or shared_ptr
that is pointing to them. So if you assign a unique_ptr
or shared_ptr
to point to your QTimer object, and also give the QTimer-object a non-NULL parent (as in your example), then you likely will have a double-delete problem: once when the Qt mechanism deletes the QTimer, and a second time when the unique_ptr
tries to delete the (now-dangling) pointer that it contains. (Note that there is a QPointer class that behaves as a weak-pointer to a QObject, which can be useful).
Because of that, it's better not to try to mix Qt's object-tree system and C++ smart-pointers. That is, if you're going to give your QTimer a non-NULL parent, then you should rely on that parent to handle the QTimer's deletion, and not also try to manage it with a unique_ptr
.
What if timer was allocated on the stack? Does *this know that?
No, this
's destructor won't know the object is on the stack, and so it will try to delete it, leading to undefined behavior. So if you're going to allocate the QTimer on the stack, you should not specify a non-NULL parent-pointer for it.