[Development] QList

Philippe philwave at gmail.com
Mon Mar 20 09:28:33 CET 2017


>>Even our API guidelines stipulate that you should make common things easy and 
>>not-so-common things possible. Sharing is _not_ common and it need not be as 
>> easy as common tasks. I

Maybe for you, but in my works, sharing _is_ common, convenient and safe.
And overal usage of COW is one of the concept that makes Qt stand apart.
From my POV, COW largely pay off its minimal performance cost.
When performance is a high priority, _an uncommon case_, then using
alternate containers is always possible and we don't need Qt for this.

And when size matters, have this in mind:

sizeof(std::vector<int>) == 32
sizeof(QVector<int>) == 8
sizeof(QList<int>) == 8

 (VC++ 64bit)

Philippe

On Mon, 20 Mar 2017 09:09:57 +0100
Marc Mutz <marc.mutz at kdab.com> wrote:

> On Sunday 19 March 2017 19:48:36 Thiago Macieira wrote:
> > On sábado, 18 de março de 2017 15:32:55 PDT Marc Mutz wrote:
> > > On Saturday 18 March 2017 19:30:35 Thiago Macieira wrote:
> > > > QVector<MyType> someFunction()  // out-of-line
> > > > {
> > > > 
> > > >         QtExclusive::QVector<MyType> vector;
> > > >         [ operate and populate vector ]
> > > >         return vector;          // automatic move
> > > > 
> > > > }
> > > > 
> > > > in user code:
> > > >         QtExclusive::QVector<MyType> vector = someFunction();   //
> > > > 
> > > > automatic move [ mutate some more ]
> > > 
> > > Breaks (N)RVO.
> > 
> > How?
> 
> Returned Type != (Declared) Return Type != Expected Type (by caller)
> 
> For NRVO, all three must be identical, for RVO the last two.
> 
> > > And since the code outside has no clue about whether the code inside the
> > > function creates a shared or unshared QVector, the compiler will again
> > > have to emit the whole QVector copy constructor/detach code (as dead
> > > code) at the call site. You promised this would be gone in Qt 6 because
> > > of the removal of the unsharable state.
> > 
> > QtExclusive::QVector's move constructor for QVector always needs to emit
> > copying code, since it doesn't know whether the data is shared or not.
> > There's no way around that.
> >
> > QVector's move constructor for QtExclusive::QVector simply adopts the data
> > and starts reference-counting.
> 
> Sure, I understand that. It's the misuse of QVector when exclusive QVector was 
> needed that is the problem:
> 
> > You could argue that a function that always returns an unshared vector
> > could return QtExclusive::QVector.
> 
> Exactly that.
> 
> > But we should not allow that in our API
> > any more that we allow returning references.
> 
> Yes, that was my fear.
> 
> The exclusive split sounded like a good idea, like unique_ptr vs. shared_ptr, 
> one that could actually win me over to support keeping any form of Qt 
> container at all, long-term. Until right now.
> 
> If you would propose to make QVector exclusive, maybe with SOO, and provide 
> QSharedVector, but to default to QVector in API, you would probably have me on 
> board.
> 
> It's a fallacy to think that there's a lot of need to return a shared 
> collection from APIs. Either you create the collection on request, then an 
> exclusive collection would be preferable, as returning it from a function is 
> free[1], or you "return" internal state, in which case returning some form of 
> view (incl. the case of simply adding begin()/end()) would be the way to go 
> (cf. https://codereview.qt-project.org/150658).
> 
> Even if your pov is that you should always return an owning collection in 
> these cases, and that it therefore has to be a shared one, existing Qt code 
> (QObject::children()) shows that even CoW is too slow in these cases 
> (children() returns by const-&). If QObject was iterable as a container of 
> QObject*, that would both be more convenient as well as faster).
> 
> [1] yes, _is_. Ville may correct me if I'm wrong, but afaiu, C++17 makes
>  (N)RVO mandatory. Sorry, GCC, you'll have to finally do something about your
>  broken NRVO.
> 
> > > > Why not std::vector? Because of the ability to put it back into shared
> > > > mode,
> > > 
> > > std::shared_ptr<const std::vector>
> > 
> > One level of indirection too many. We've been over this.
> 
> iow: you'd rather pay some large overhead every time than pay a larger one 
> only in cases where it's needed. And this is where we fundamentally disagree.
> 
> Even our API guidelines stipulate that you should make common things easy and 
> not-so-common things possible. Sharing is _not_ common and it need not be as 
> easy as common tasks. Iteration, builing a container from scratch, returning 
> by NRVO from a function, these are common things. And CoW pessimises such 
> common things - not only performance-wise, but also conceptually: std::vector 
> doesn't need qAsConst when used with ranged for loops, std::vector doesn't 
> invalidate iterators when copied from...
> 
> 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, C++ and OpenGL Experts
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development





More information about the Development mailing list