Sneak Preview: QList considered harmful
2010-07-29 14 Comments
[[EDIT 2011-08-15: This has since been extended into a full Effective Qt column.]]
We knew for a long time that
QList is not a good default container, despite what the documentation claims. The problem boils down to the fact that for a lot of types
QList<T> is needlessly inefficient by allocating elements on the heap and storing pointers to them instead of storing the elements in-place, like e.g.
QVector does. Sometimes, for large and complex types, that might be exactly what you want, but a conservative estimate would put that chance at less than 5%.
It never ceases to amaze me how people trained in the STL default to
std::vector until a profiler tells them that they should use a
std::deque instead, whereas people trained in Qt default to
QList and not
Effective Qt will soon come out with all the gory details, but since KDE’s 4.5 and Qt’s 4.7 releases are imminent, I decided to give you a sneak preview of just how widespread this inefficiency is. In order to do that, I finally sat down and developed a patch that emits a warning when you try to add something to an inefficient
QList (at least if you set your compiler to warn for signed/unsigned integer comparison warnings). It’s been developed and tested with GCC 4.3 and Qt 4.6.3, but should work for a lot of other compilers, too. Please send me warning generators for your compiler in comments.
The patch is binary-compatible, so you don’t have to recompile your Qt after applying it.
Here’s a (incomplete) list of inefficient uses of
QList (in the following,
S are arbitrary type):
QVariant(!!) is too large.
QVector<T>isn’t marked as movable, even though it is.
QSharedPointer<T>is too large.
- Virtually any
QPair<T,S>is too large.
- Enums not marked as movable.
Run, don’t walk, and fix your new API to not use
QList, or mark your new types as movable (details are in the patch). Alas, both changes are binary incompatible, so you can’t do them if you need your code to stay BC. This might be one of the reasons why
QVector aren’t “fixed” yet: doing so would change the layout of the
QList instantiated with them :(.
But, at least for new code, there’s no excuse anymore: Just apply the patch.