[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