
[[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 T
, 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::list
or std::deque
instead, whereas people trained in Qt default to QList
and not QVector
.
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, T
and 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 QPair
and 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.