MAY
13
2015

Simple Qt container optimization you should do on your code

Most of us know we shouldn't let our containers detach. QList, QVector, QString, etc. are implicitly shared. Copying them is cheap, but when we call a non const member function it will detach and trigger a deep copy.

This is common knowledge, but we still forget and do:
Item item = fetchJob->items().first();
instead of:
Item item = fetchJob->items().at(0);

Last weekend I started looking into "proper tooling" to help detect cases where we're detaching but was quickly sidetracked by "rudimentary tooling", which kept me busy fixing 50 detaches in kdepim, some of them quite expensive.

So, just run grep -R \)\\.first\(\) in your source directory.
Chances are you'll find lines where you're detaching from temporary containers and it's very easy to fix.

Beware of false positives: if the container isn't shared it wouldn't detach. For example, QMap::keys() returns a fresh QList created on the fly with refcount = 1. In doubt use the source.

Expect a new blog post with proper tooling soon.

UPDATE: peppe is working on adding rvalue overloads so that it never detaches when calling first()|last() on temporaries (https://codereview.qt-project.org/#/c/112343/)

Comments

Yet another Qt API glitch. The same goes for using qt containers with c++11's range-for.

There were proposals to add a

as_const<T>(...)

function template to the standard library, but I guess we'll have to wait for that. (if it ever happens)


By Ivan at Sat, 05/16/2015 - 16:46

Another case where calling first() is safe is when you're operating on a const SomeContainer &. Then it will call the const overload of first(), which does not detach. In fact, it is a good idea to operate on const references to containers whenever you can, because those actually cannot detach.


By Kevin Kofler at Sun, 05/17/2015 - 22:15

Thank you for this Trick


By Jack at Sun, 03/06/2016 - 21:40