You have probably heard how it has been said that in some corporate organizations that pointers have been banned when coding in C++. Then you would know that this is really awkward for any C++ programmer to not use Objects in their code.
Anyway, there is a sane way to handle your memory management issues when programming with Qt and that is to use one of the pointer classes called QPointer provided in the Qt framework.
Before we go much further, this post expects you to have an idea of programming in C++ and it also expects you to know the basics of the Qt framework. If you are not familiar with what Qt is you can get an idea from The Qt Company.
If you are not familiar with C++ then I would advise you to read another article on this website about C++ and when you have time Google the word “C++” and follow on the documentation and tutorial resources available on the Internet.
Before We Deal With QPointer
We will look at two general ways in which Qt manages memory and how it takes care of pointers so that we do not have to worry about it as much. I will give just a quick note on what pointers are in C++ and why they are so dangerous to use before we get on with this post.
What is a C++ Pointer?
If you are already familiar with C++ then this section is not for you. However, for argument’s sake, I will still mention what a pointer is. A pointer is in simplest terms, an object that stores the memory address of another object or primitive type. Take for example:
The first of the three lines describe the declaration of locations in memory identified by i and j which occupy the size of an int. An int depending on the computer architecture can be 4 or more bytes. Let us just hold this assumption to be true for now.
The second line in the code above simply declares a pointer that points to the memory address of an integer which is specifically named I while the third line redirects the pointer to point to a location in memory which is an int wide and is marked by the name j. Simple enough.
The Problem With Pointers
Now pointers are known to be dangerous because they are in most times at the chore of memory leaks. A memory leak is a situation where you have memory on your heap that cannot be accessed by your program or any other program because as far as the computer is concerned, that memory is still in use.
How do Memory Leaks Occur?
Memory leaks occur when pointers referencing a certain chunk of memory goes out of scope and therefore the pointer is lost but the content that the pointer was referencing is still lying in the heap. A pointer would normally go out of scope when an execution block ends and returns and the pointer created within that scope is not destroyed along with the referenced data.
This can also occur when an exception is thrown or when any sort of error stops execution before the pointer is destroyed.
So How is This Pointer Problem Handled in Qt C++
Now a little bit about Qt first. Qt is a Framework that comprises of several classes that form the Qt object model. The root of this model is the QObject class. Basically, all Qt objects inherit from the QObject class. Having inherited from this class, it means all Qt Objects inherit a particular behavior and we can exploit this in order to manage memory.
Now a QObject based class looks something like the code below:
The header file
The source file.
From the code above you will notice that any Qt class that inherits from QObject also takes up the parent-child relationship that comes along with it. Basically, every QObject derived class can have a parent or can have children.
The parent can be defined in the class contractor as shown above. Now comes the interesting part. One great thing about QObject based classes is that once a parent is destroyed all the children are destroyed along with it and therefore when creating QObject derived classes in our projects. It would be a good idea to specify the parent.
Let us pretend that we have a QObject based class called MyChild and we include its header file in our MyOject class header. We can add a pointer to the MyChild class like so:
We cannot initialize this in a C++ header file so we will have to do it in the source file contractor to look something like this:
We have now initialized our pointer but the problem here is that this is a dangling pointer. Once MyObject is destroyed this pointer will still remain in memory, therefore, creating a memory leak. There is one usual way we can take care of this C++ and it is to use something like this:
This can be placed somewhere in your class where the pointer will no longer be used. One good place is in the destructor. Now the problem with this is that if any exception occurs between creation and deletion of the pointer then we run into the danger of still having a memory leak.
This may not be entirely true though with some operating systems which would pre-allocate a certain amount of memory to a program and f the program is destroyed that memory is released. This may be okay for some applications or where the pointer is used within the application.
Without going into the complexities involved we can take a look at how Qt handles this problem by exploiting the parent-child relationship.
Looking at the initialization of the pointer above, all we need to do is modify that line as follows:
child = new MyChild(this);
That’s it. Adding the
this pointer makes the this pointer a child object. Now we do not need to worry about deleting the pointer as it will be destroyed along with the parent.
Memory Management Using QPointer
Another way we can manage memory in Qt is using the guarded pointer QPointer. QPointer can be used on all classes based on QObject. You would normally use QPointer in a situation where the pointer is being created outside of a QObject class such as in the main function or other none Qt based classes you may have created in your code.
Here is how you can use it:
The QPointer is a template class that wraps obj as a pointer to MyObject. You will notice that there is no star to mark it as a pointer because QPointer abstracts all that. It does not just stop there but it also deals with dynamically destroying the obj pointer should there no longer be any references to it.
There you have it. A simple and safer way to use pointers and to manage your memory when programming in Qt C++.
Other pointer classes in Qt that could interest you are:
- Tracking QObjects: QPointer – This tracks the lifetime of an instance of QObject.
- Shared Data Pointers: QSharedDataPointer, QExplicitlySharedDataPointer – Ideal for sharing of non-pointer data. They are also known as intrusive pointers.
- Shared Pointers: QSharedPointer, QWeakPointer – These are thread-safe sharing pointers, similar to C++11’s std::shared_ptr. QWeakPointer use has been deprecated unless used with QSharedPointer.
- Scoped pointers: QScopedPointer, QScopedPointerArray – These are none shared pointers Ideal for Resource Acquisition Is Initialization (RAII) usage whereby they take ownership of a pointer and ensures it is properly deleted at the end of the scope.
For further C++ reading on libraries, you can follow this article series on the C++ Standard Template Library here.