[Development] Move ctors for q_declare_shared types
Marc Mutz
marc.mutz at kdab.com
Fri Jun 26 10:45:24 CEST 2015
Hi,
I'd like to invite review of
https://codereview.qt-project.org/115213
despite it clearly not being in a mergeable state (mixes unrelated changes).
It introduces a new shared data pointer that's designed to allow users of the
pointer to have an inline move constructor.
Most of our implicitly shared types already had a move-assignment operator,
because it's just
QFoo &operator=(QForr &&other) { swap(other); return *this; }
and member-swap was enforced by Q_DECLARE_SHARED since Qt 5.0. I have uploaded
a series of changes that makes (almost) all Q_DECLARE_SHARED types in qtbase
nothrow move constructible. That's good. But far from enough.
What is _really_ important to have for _any_ value type is to have nothrow
move *constructors*, because that's what std::vector uses when reallocating.
So far, adding move ctors was thwarded by the compiler insisting on
instantiating ~Q(Explicitly)SharedDataPointer() in the obvious move ctor
implementation:
QFoo(QFoo &&other) : d(std::move(other.d)) {}
(see http://stackoverflow.com/questions/9417477), which of course fails in
header files where the shared data pointer's payload is merely forward-
declared.
Having naked pointers instead of smart ones as d-pointers works, see. eg.
QUrl, but moving all classes back to naked d pointers would be highly
controversial, and we'd lose the safety net of deep const propagation that at
least QSharedDataPointer provides (QExplicitlySharedDataPointer doesn't).
The idea is explained in the change's commit message, so I will not repeat it
here.
But I'd like to get some feedback on the patch before I run off and port all
Q_DECLARE_SHARED classes over to the new smart pointer, and then someone pulls
the plug like with Q_STRINGTABLE-
It's a bit urgent, because I'd like to have complete coverage in by 5.6, so
please have a look.
Q_DECLARE_SHARED will at some point start to enforce the presence of a nothrow
move assignment operator, then, later, a nothrow move ctor.
Mid-term goal would be to have all implicitly-shared classes use the same
smart pointer, be nothrow move-assignable, nothrow move-constructible, and
nothrow *default-constructible* (which requires a trick a la QRegion / QString
/ QVector / QList (QtPrivate::RefCount and a shared null state, or else a
nullptr d-pointer)), probably by Qt 5.7.
If you don't believe this matters, see comment in qdatetime.h:
// ### Qt6: Using a private here has high impact on runtime
// on users such as QFileInfo. In Qt 6, the data members
// should be inlined.
And no, it's not mine. Someone actually measured and found it to be
unacceptable. Specifically, that the default ctor allocates memory. In fact,
it's *so* unacceptable that QFileInfo now contains a QVector<QFileInfo>
instead of a QFileInfo[3], which at face value is ridiculous, but delays
memory allocations until they are actually needed.
Thanks,
Marc
--
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
More information about the Development
mailing list