2. Overview
Memory management in C++ is left up to the
programmer.
Smart pointers are the preferred way in C++ to
ensure correct management of dynamic memory
allocated by new expressions.
Smart pointers are similar to regular pointers, but
take care of the details of deleting the object being
pointed to when it is no longer needed.
The C++ Standard Library already contains
std::auto_ptr, a smart pointer with transfer-of-
ownership semantics.
New C++ Standard may be issued by the end of
2010 and it will introduce new smart pointers.
2 7 February 2010
3. General
Shared pointer versus shared data
When you share pointers, the value of the pointer and its
lifetime is protected by the smart pointer class but the object
that the pointer is pointing to is completely outside its control.
Sharing of data involves the smart pointer class knowing
something about the data being shared (Implicitly Shared Qt
Classes).
Strong versus weak pointer
Strong pointers own the object they point to. Multiple strong
pointers can share ownership. An object is guaranteed to stay
alive as long as at least one strong pointer still points to it.
Weak pointers observe an object. They can be used exactly
like strong pointers, but they do not keep their object alive. If an
object is destructed, all of its weak pointers will be valued null.
3 7 February 2010
4. C++0x smart pointers
std::shared_ptr<>
The shared_ptr is a reference-counted pointer that acts as
much as possible like a regular C++ data pointer. The shared
pointer will automatically destroy its contents only when there
are no shared pointers referencing the object originally created
for the shared pointer.
std::weak_ptr<>
A weak_ptr is a reference to an object referenced by a
shared_ptr that can determine if that object has been deleted or
not. weak_ptr itself cannot be dereferenced; accessing the
actual pointer requires the creation of a shared_ptr object.
std::unique_ptr<>
unique_ptr will be provided as a replacement for auto_ptr which
will be deprecated. It provides all the features of auto_ptr with
the exception of unsafe implicit moving from lvalues. Unlike
auto_ptr, unique_ptr can be used with the C++0x move-aware
containers.
Currently GCC since 4.3 and MSVC 2010 support C++0x
4 7 February 2010
6. QPointer
QPointer is a weak pointer class and it shares the pointer
value, not the data.
It only operates on QObject and QObject-derived classes.
QPointer has one serious flaw: it lets you know whether the object
has been deleted, but it makes no guarantee about the next line!
For example, the following code could be in trouble:
QPointer<QObject> o = getObject();
// […]
if (!o.isNull())
o->setProperty(“objectName”, “Object”);
Even if isNull() returns false, there’s no guarantee that the object
won’t get deleted by the next line.
Therefore, QPointer can only be used to access the object if
you can guarantee, by external means, that the object won’t
get deleted. For example, QWidget and its descendents can
only be created, manipulated and deleted in the GUI thread. If
your code is running on the GUI thread or has that thread
blocked, then QPointer usage is safe.
6 7 February 2010
7. QSharedDataPointer
The most important of the smart pointer classes in Qt.
It provides implicit sharing, with thread-safe copy-on-write.
The QSharedData class is used as a base class for shared data objects.
QSharedDataPointer requires that the class have a member called ref (see QAtomicInt member in
QSharedData class)
The member offers a function called ref() for increasing the reference count and another called
deref() that decreases that reference count and returns false when it drops to zero.
QSharedDataPointer members:
inline void detach() {if (d && d->ref != 1) detach_helper();}
inline T * operator->() {detach(); return d; }
inline const T *operator->() const { return d; }
private:
T *d;
Any non-const access will cause the data to be copied.
The size of a QSharedDataPointer object is exactly the size of a pointer
That means it’s possible to replace normal pointers with it in the code without breaking Binary
Compatibility.
This class is the basis of all Qt value-type, implicit-shared, thread-safe copy-on-write recent
classes.
The only reason why it isn’t used in the base classes like QByteArray, QString and QList is that those
classes were developed before this class was made.
So QSharedDataPointer is a strong smart pointer class, sharing data.
7 7 February 2010
8. QExplicitlySharedDataPointer
The QExplicitlySharedDataPointer class represents a pointer
to an explicitly shared object.
This class is exactly like QSharedDataPointer (so it’s a strong
smart pointer class, sharing data), with the only difference that
it do not do the automatic copy on write operation (detach())
that non-const members of QSharedDataPointer do before
allowing the shared data object to be modified.
There is a detach() function available, but if you really want
to detach(), you have to call it yourself. This means that
QExplicitlySharedDataPointers behave like regular C++
pointers, except that by doing reference counting and not
deleting the shared data object until the reference count is 0,
they avoid the dangling pointer problem.
QExplicitlySharedDataPointer members:
inline void detach() {if (d && d->ref != 1) detach_helper();}
inline T *operator->() { return d; }
inline const T *operator->() const { return d; }
8 7 February 2010
9. QSharedDataPointer versus
QExplicitlySharedDataPointer
class EmployeeData : public QSharedData // can be defined in a separate file
{
public:
EmployeeData() : id(-1) { name.clear(); }
EmployeeData(const EmployeeData &other)
: QSharedData(other), id(other.id), name(other.name) { }
~EmployeeData() {}
int id; QString name;
};
//------ the public file ------------------------------------------------------
class EmployeeData; // predeclare the private subclass
class Employee
{
public:
Employee() { d = new EmployeeData; }
Employee(int id, QString name) {d = new EmployeeData(); setId(id); setName(name);}
Employee(const Employee &other) : d (other.d) {}
void setId(int id) { d->id = id; }
void setName(QString name) { d->name = name; }
int id() const { return d->id; }
QString name() const { return d->name; }
private: // a copy constructor or an assignment operator are not needed
QSharedDataPointer<EmployeeData> d;
};
int main(int argc, char *argv[])
{
Employee e1(1001, "Albrecht Durer");
Employee e2 = e1;
int i = e2.id();
e1.setName("Hans Holbein"); // a copy on write is performed for QSharedDataPointer
}
9 7 February 2010
10. QSharedPointer
The QSharedPointer class holds a strong reference to a shared
pointer.
The QSharedPointer is an automatic, shared pointer in C++. It
behaves exactly like a normal pointer for normal purposes, including
respect for constness.
it is polymorphic, it supports static, const, and dynamic casts, it implements
atomic reference-counting and thread-safe semantics (it’s only for the
pointer itself: remember it shares the pointer, not the data), it supports
custom deleters.
QSharedPointer will delete the pointer it is holding when it goes out of
scope, provided no other QSharedPointer objects are referencing it.
A QSharedPointer object can be created from a normal pointer,
another QSharedPointer object or by promoting
a QWeakPointer object to a strong reference.
It comes with a cost, though: to support polymorphism correctly, the
size of QSharedPointer is actually twice the size of a normal pointer.
This means you cannot maintain binary compatibility while replacing a
normal pointer with it in public parts of your API. You can use it
internally in your code, though.
10 7 February 2010
11. QWeakPointer
The QWeakPointer class holds a weak reference to a shared
pointer.
The QWeakPointer is an automatic weak reference to a
pointer in C++. It cannot be used to dereference the pointer
directly, but it can be used to verify if the pointer has been
deleted or not in another context.
QWeakPointer objects can only be created by assignment
from a QSharedPointer and they let you know when a
QSharedPointer has been deleted.
QWeakPointer<Data> weak(getSharedPointer());
QSharedPointer<Data> ptr = weak.toStrongRef();
if ( !ptr.isNull() )
ptr->doSomething();
In this case, the promotion of a QWeakPointer to a
QSharedPointer will either succeed or it won’t. But that’s a thread-
safe decision.
QWeakPointer can be used to track deletion classes derives
from QObject. It is more efficient than QPointer, so it should be
preferred in all new code.
11 7 February 2010
12. QScopedPointer
The QScopedPointer class stores a pointer to a dynamically allocated object, and
deletes it upon destruction.
It provides a very nice way to do RAII (Resource Acquisition Is Initialization).
It implements a non-shared strong pointer wrapper.
QScopedPointer guarantees that the object pointed to will get deleted when the
current scope disappears.
It intentionally has no copy constructor or assignment operator, such that ownership
and lifetime is clearly communicated.
void myFunction(bool useSubClass)
{ // assuming that MyClass has a virtual destructor
QScopedPointer<MyClass> p(useSubClass ? new MyClass() : new MySubClass);
QScopedPointer<QIODevice> device(handsOverOwnership());
if (m_value > 3) return;
process(device);
}
QSharedPointer has the size of two pointers.
It also has a custom deleter as a template parameter, as opposed to a parameter to
the constructor (like QSharedPointer does): it has no space in those 4 or 8 bytes to
store the custom deleter.
QScopedPointer and QExplicitlySharedDataPointer are already used all over the
place in the Qt for S60.
12 7 February 2010
13. References
Pointer (computing)
Smart pointer
C++0x
Introducing QScopedPointer
Count with me: how many smart pointer classes
does Qt have?
13 7 February 2010