[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