An important rule of thumb for good coding practices is
every
newmust 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.
- Can I call
delete timer;anyway, such as in the destructor of aunique_ptr? Will that call the destructor twice? - What if
timerwas allocated on the stack? Does*thisknow that?
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.With
unique_ptr(orshared_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 aunique_ptrorshared_ptrthat is pointing to them. So if you assign aunique_ptrorshared_ptrto 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 theunique_ptrtries 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.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.