| 1 |
QPointer |
| 2 |
==================== |
| 3 |
QPointer is a guarded pointer for QObjects, so it automatically becomes 0 when |
| 4 |
the data it points to is deleted. If you have a member variable that's a QObject |
| 5 |
and are ever worried that it might be dangling, make it a QPointer. There's |
| 6 |
really no reason not to for variables that stick around, it adds little |
| 7 |
overhead. |
| 8 |
|
| 9 |
KSharedPtr |
| 10 |
==================== |
| 11 |
Unlike QPointer, KSharedPtr is dangerous and must be used carefully. |
| 12 |
|
| 13 |
== Undercounting == |
| 14 |
KSharedPtr uses reference counting. When a KSharedPtr is in scope, it adds one |
| 15 |
to the reference counter. When a KSharedPtr loses scope, it deletes one from the |
| 16 |
reference count. When the reference count become 0 it deletes the object. So if |
| 17 |
there were any normal pointers to that data and all the KSharedPtrs are deleted, |
| 18 |
then the object is deleted and the normal pointers dangle. Segfaults ensue. |
| 19 |
|
| 20 |
The solution is to just make sure that any normal pointers are temporary and |
| 21 |
everything else is a KSharedPtr if reference counting is required for your class. Even |
| 22 |
if the pointer is temporary, but is then handed off to some other class that |
| 23 |
might keep it around, thats a potentional crash now or in the future. |
| 24 |
|
| 25 |
|
| 26 |
== Reference Cycles == |
| 27 |
One issue with reference counting in general is the creation of a reference |
| 28 |
cycle. If class A has a KSharedPtr<B> property and class B has a KSharedPtr<A> |
| 29 |
property and two objects of A and B point to each other and the KSharedPtrs |
| 30 |
loose scope, a reference cycle is created. Despite not being accessible from |
| 31 |
anywhere in the program, the reference counter of KSharedPtr<A> and |
| 32 |
KSharedPtr<B> will never go to 0. Memory leaks. The solution is to be careful. |
| 33 |
|
| 34 |
== Dreaded Diamonds == |
| 35 |
Since the objects KSharedPtr point to must derive from QSharedData, it's not |
| 36 |
uncommon for a "dreaded diamond" inheritance issue to arise. Basically if A and |
| 37 |
B both inherit QSharedData and C inherits A and B, then C inherits QSharedData |
| 38 |
twice. The solution is really easy, just add a 'virtual' keyword when A and B |
| 39 |
inherit QSharedData. Eg class A : public virtual QSharedData. Details at: |
| 40 |
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8 |