[Development] Move ctors for q_declare_shared types

Thiago Macieira thiago.macieira at intel.com
Fri Jun 26 22:52:17 CEST 2015


On Friday 26 June 2015 10:45:24 Marc Mutz wrote:
> 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.
[snip]
> Q_DECLARE_SHARED will at some point start to enforce the presence of a
> nothrow move assignment operator, then, later, a nothrow move ctor.

Hi Marc

Thank you for the change, I think this is a good way forward.

As you can see in my comments in the change, I'd just like to explore a way to 
make the code less ugly by having fewer macros required in the public headers.

For example: can we make the deallocation function a member of the front-end 
class, which is usually exported anyway? This would avoid the ugly need for 
two macros in a row like:

	Q_GUI_EXPORT Q_SHAREDDATAPOINTER_DECLARE_DTOR(QFontPrivate);

Wouldn't the fact that it's a member function remove the need for the 
declaration prior to the class instantiation?

We may need a macro anyway, which I'd advise be called 
Q_DECLARE_PUBLIC_SHARED(ClassName)

> 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.

Some of those classes are bigger than one pointer and/or may hold more than 
one pointer (for example, QSharedPointer).

I've been playing with null d pointers for the past 3 years and I've never 
made it work and I wasn't even trying to keep BC.

> 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.

Which is also why I inlined the begin() pointer into 
QString/QByteArray/QVector, so it doesn't dereference the d pointer to find out 
where it's going to be.

At the same time, I made QUrl not be shared at all. Too much headache.
-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center




More information about the Development mailing list