In my c++ code, I often have blocks like this:
if (m_pointer) {
delete m_pointer;
m_pointer = nullptr;
}
I just wonder, whether there is a better, designated, way to do it than repeating this block all over my code. Smart pointers are not an option here, since it’s all about QObjects
, which don’t really support them afaik.
11
Since deleting a nullptr is safe, you don’t need to check, and to set it to nullptr you can just “exchange” it.
#include<utility>
...
delete std::exchange(m_pointer, nullptr);
https://godbolt.org/z/eKqh7oWPW
But if you are looking for this kind of automaticity, consider using std::unique_ptr
instead.
Here is GCC producing identical machine code for the two types of constructs: https://godbolt.org/z/aP5hsT7fv
NB: This is not as interesting or useful as it looks, why? because any non-trivial use of null state for a pointer generally also controls other parts of the logic of the program or the class for which this pointer is a member.
In these cases you need to do the if(m_pointer)
conditional anyway to control that.
And in the cases where this is trivial, you can already use std::unique_ptr
, which precisely tracks its internal state through a null pointer.
Finally, putting this kind of code in destructors is controversial at best, because there is no need to set a member variable that is about to expire.
3
If you are working with QObjects you could use QPointer which is automatically cleared inside the QObject destructor, you just need to delete m_pointer.get();
and all connected QPointers will be turned null.
This is Qt’s way of having weak smart pointers, other GUI libraries likely have one too, ie: wxWeakRef and Gobject.WeakRef (C++ version is in glibmm).
It is usually a good idea to search your framework documentation for weak references or pointers.
Note: As a special exception a QObject
can store std::unique_ptr
to its children because the unique_ptr
will be destroyed before the parent, and destroying an object unparents it, and you can just set the unique_ptr
to nullptr to destroy the object, but if you are not the parent or you are in doubt then use QPointer
instead. (For example if you are going to use deleteLater
then you must use QPointer
)
I am not familiar with Qt and cannot confirm if QObject
can be used with smart pointers. If it can – this is the right path.
If you must manage a raw pointer manually, you can use this function template:
template <typename T>
void safe_delete(T*& p)
{
delete p;
p = nullptr;
}
And the usage:
safe_delete(m_pointer);
Note that there’s no point checking if p
is nullptr
assuming the default operator delete is used (because it is guaranteed to do nothing with a null pointer).
If you want to avoid a template for some reason (which I cannot foresee), you can use a macro:
#define SAFE_DELETE(p) { delete p; p=nullptr; } while (0)
And the usage:
SAFE_DELETE(m_pointer);
Note: usually macros are not recommended, but in this specific case I believe it is somewhat acceptable (but the template version is preferable).
13
Smart pointers are not an option here, since it’s all about QObjects, which don’t really support them afaik.
You are mistaken. Qt interacts with smart pointers fine. It doesn’t use them in its examples, because they all relate to objects with parent-child relationships, which Qt also manages within the class QObject
. It’s perfectly fine to use smart pointers. ~QObject()
will remove this
from the parents list of children, if there is a parent.
Most of the time, the reason you want to delete
a pointer is that the lifetime of the pointer is about to end. You don’t need to null it, because nothing can read the value. In the rare occasions that the pointer is continuing to exist, it would be better to use a smart pointer, and reset()
it.