[Development] Heads up: QWeakPointer re-education

Mutz, Marc marc at kdab.com
Fri Aug 16 11:02:35 CEST 2019


Hi,

It seems that the presence of QWeakPointer::data() in the past has given 
many Qt developers the wrong impression and they're now fighting hard to 
keep that impression intact when porting away from deprecated data().

So here's some re-education. Ignore at your own peril :)

= Lesson 1: weak_ptr is not a pointer =

A weak_ptr is an opaque pointer store/an observer. It is not a pointer: 
You cannot deref it, and these days you also can't convert it to a raw 
pointer anymore.

You can ask whether it's expired, but that answer is useless the moment 
it is given, unless you ask for a conversion to shared_ptr, in which 
case you get a _real_ pointer back (or nullptr), and _that_ answer 
remains valid for as long as you hold on to the shared_ptr.

In this is differs from QPointer, which is _also_ observing (resetting 
itself to nullptr upon deletion of the payload), but is also a pointer: 
you can deref it, and, since it doesn't really work across threads, it 
won't be killed under you (though I hasten to add that you just need to 
grep for "that = this" to find places where it more or less actually 
is).

So, remember: weak_ptr is not a pointer. QWeakPointer is _not_ QPointer.


= Lesson 2: forget .data() existed =

QWeakPointer::data() is gone. Forget also about QSP::data(): You need it 
only when you'd also need it on QScopedPointer: when you need to pass 
the address of the owned object to a raw pointers API. So, almost never.

In particular, use op-> and op*, not .data(). Use the shared_ptr as a 
pointer, don't run to extract a raw pointer stat and then forget the 
shared_ptr.


= Lesson 3: if you need to use .data() treat it the same as 
QByteArray::data() =

That is, don't call it on rvalues unless you pass the result to a 
function that doesn't store it. In any other case, store the owning 
object in a named variable and call .data() on _that_. This pins the 
lifetime of the data to the current scope, and prevents use of dangling 
pointers.


= Lesson 4: idioms are good =

Handwaving a la "we don't use MT, so we don't need this" etc is ignoring 
the fact that what I described above a) is idiomatic use of weak_ptr and 
b) any non-idiomatic use is more complex to reason about.

This is idiomatic use:

    auto x = weak_x.toStrongRef();
    ~~~
    x->~~~
    x->~~~

There's nothing wrong with that code, there's no need for a comment. 
It's just what you do when you want to access the object hidden in a 
weak_ptr. If anything, you should add an assertion and explain why you 
expect x to never be nullptr.

This is non-idiomatic use:

    auto x = weak_x.toStrongRef().data();
    ~~~~
    x->~~~
    x->~~~

That also doesn't need a comment. It needs to be re-written into 
idiomatic form :)

Thanks for listening,
Marc


More information about the Development mailing list