[Development] QList

Olivier Goffart olivier at woboq.com
Tue May 23 13:56:52 CEST 2017


Am Donnerstag, 18. Mai 2017, 10:58:23 CEST schrieb Ville Voutilainen:
> [...] the QUIP is here for review:
> https://codereview.qt-project.org/#/c/194984/

Thanks, 
(Sorry for not replying to the QUIP, but discussions on gerrit are not so easy 
to follow)

Here are what  what are the characteristics of QList:

a. Amortized O(1) append
b. Amortized O(1) prepend
c. Relatively fast insert even if elements are expensive to copy/move
d. Implicitly shared (copy-on-write)
e. Should expand to less binary code than QVector or other container because 
most operation are done in qlist.cpp, common for very type. (I don't think 
this was mentioned before)
f. The pointers to elements are kept valid on append/prepend/insert if the 
list is not shared (detach) and the type is big enough.
g. It is inefficient because of the many allocations and bad cache behaviour.


In Qt 4.0, QList was made the default container for most purposes because of 
the points a,b,c,d,e which where believed to be good characteristics for a 
default sequence containers. I don't think f was an intended characteristic. 
(Actually, I believe that people who rely on it just rely on an accidental 
implementation detail / undefined behavior.)
And g was somehow ignored for some reason, or maybe it was tough that c was 
more important for the default container.

The question is what to do in Qt 5.x and in Qt 6?

QList being used everywhere means people might rely on any of these point.

It was suggested to simply replace making QList being an alias to QVector in 
Qt6. But we'd loose characteristics b,c,e,f.   
We could get b. back if we make it possible for QVector to reserve memory in 
front on prepend.
We could ignore c. as this might be less of a problem with move semantic 
nowadays. We could also ignore e.
But not having f. might introduce nasty bugs that might not be seen easily in 
big project while porting. So Marc suggested adding a QArrayList alias to 
annotate code today that we know are relying on f. as a porting aide.

I think QArrayList does not solve the problem because I'd say most people will 
not use it, they might not even know they rely on it. Their code works now, 
and if we replace QList by QVector it will introduce subtle bugs anyway.

Another solution could be to keep QList as it, but deprecate it, and use 
QVector everywhere in the API. We'd need to introduce implicit conversion 
between QList and QVector to reduce the amount of source incompatibilities.

An alternative could be to develop a new data structure that keep the 
good part of QList, while keeping good cache behavior. Maybe something modeled 
around std::deque. 


In my opinion for Qt6, we should make prepend, takeFirst amortized O(1) in 
QVector. And change the API to use QVector everywhere, with QList being a 
deprecated alias to it. Ignore the fact that people can keep pointers to the 
items. (Small behavior change that should not impact many usages.)

(For functions that do not take ownership of the vector, I'd make a new a 
QArrayView.)

-- 
Olivier

Woboq - Qt services and support - https://woboq.com - https://code.woboq.org




More information about the Development mailing list