191

What are the pros and cons of using Qt containers (QMap, QVector, etc.) over their STL equivalent?

I can see one reason to prefer Qt:

  • Qt containers can be passed along to other parts of Qt. For example, they can be used to populate a QVariant and then a QSettings (with some limitation though, only QList and QMap/QHash whose keys are strings are accepted).

Is there any other?

Edit: Assuming the application already relies on Qt.

Julien-L
  • 4,913
  • 3
  • 31
  • 47

14 Answers14

184

This is a difficult to answer question. It can really boil down to a philosophical/subjective argument.

That being said...

I recommend the rule "When in Rome... Do as the Romans Do"

Which means if you are in Qt land, code as the Qt'ians do. This is not just for readability/consistency concerns. Consider what happens if you store everything in a stl container then you have to pass all that data over to a Qt function. Do you really want to manage a bunch of code that copies things into/out-of Qt containers. Your code is already heavily dependent on Qt, so its not like you're making it any more "standard" by using stl containers. And whats the point of a container if everytime you want to use it for anything useful, you have to copy it out into the corresponding Qt container?

rpg
  • 7,518
  • 2
  • 36
  • 43
Doug T.
  • 59,839
  • 22
  • 131
  • 193
  • 1
    +1 you totally right, that's what I tried to explain in my question ("I can see one reason to prefer Qt") so I edited it slightly. Thanks – Julien-L Nov 04 '09 at 09:08
  • Absolutely well said. If you're doing QT, use the QT stuff! Imagine the "WTF" moment for the maintainer when he opens a QT application and sees QT and STL used interchangeably. That could end up being an (unnecessary) nightmare. – It'sPete May 27 '14 at 07:55
  • 5
    @It'sPete STL is part of the standard; QT is not. Any code that makes use of the standard should never trigger a "WTF" moment. – Alice May 27 '14 at 17:04
  • 7
    The Romans put their captives into the Colosseum and then hunted them down with lions. If you know better, don't follow local habits. That's as true in Qt as it would have been for Modern Man in the Roman Empire... – Marc Mutz - mmutz Jan 06 '15 at 12:40
  • 1
    @mmutz you say that like it's a bad thing, I'd like to put some code I've found in that Colosseum and watch the show – slf Jun 05 '17 at 22:26
140

I started by using std::(w)string and the STL containers exclusively and converting to/from the Qt equivalents, but I have already switched to QString and I find that I'm using Qt's containers more and more.

When it comes to strings, QString offers much more complete functionality compared to std::basic_string and it is completely Unicode aware. It also offers an efficient COW implementation, which I've come to rely on heavily.

Qt's containers:

  • offer the same COW implementation as in QString, which is extremely useful when it comes to using Qt's foreach macro (which does a copy) and when using meta-types or signals and slots.
  • can use STL-style iterators or Java-style iterators
  • are streamable with QDataStream
  • are used extensively in Qt's API
  • have a stable implementation across operating systems. A STL implementation must obey the C++ standard, but is otherwise free to do as it pleases (see the std::string COW controversy). Some STL implementations are especially bad.
  • provide hashes, which are not available unless you use TR1

The QTL has a different philosophy from the STL, which is well summarized by J. Blanchette: "Whereas STL's containers are optimized for raw speed, Qt's container classes have been carefully designed to provide convenience, minimal memory usage, and minimal code expansion."
The above link provides more details about the implementation of the QTL and what optimizations are used.

rpg
  • 7,518
  • 2
  • 36
  • 43
  • 13
    In the new standard c++0x COW is pretty much off the table. –  Jan 02 '11 at 15:40
  • 17
    re: "carefully designed to provide [...] minimal memory usage". You shouldn't believe marketing. Profile `QList` on a 32-bit architecture for memory use to see for yourself. – Marc Mutz - mmutz May 03 '11 at 05:34
  • 11
    "It also offers an efficient COW implementation": COW isn't all that efficient when it comes to multithreaded applications... – Grizzly May 16 '13 at 14:27
  • 5
    @MarcMutz-mmutz try to profile `QVector` instead of `QList`. There are pretty Qt explanation, that QList is designed to store pointers on objects. So each double item created dynamically and pointer to this item is stored to `QList`. QList is designed as "middle" container between vector and linked list. It is not designed for memory/performance critical cases. – Dmitry Sazonov May 20 '14 at 13:49
  • some of us want "raw speed" – user1095108 May 24 '14 at 16:41
  • 2
    @user1095108 There's nothing wrong with that. Go use the stl. Some of us prefer writing correct code quickly. There's nothing wrong with that either. – weberc2 Jun 25 '14 at 15:59
  • 1
    @weberc2 in principle, yeah, but the exceptions STL containers throw (and QTL containers don't), do serve to remind you of some often-missed errors. Not only faster, they are also stricter. – user1095108 Jun 26 '14 at 06:20
  • 2
    @user1095108 Like what? Serious question--I haven't had much problem with QTL containers. – weberc2 Jun 26 '14 at 13:24
  • 2
    The issue I've encountered had to do with insert and associative containers. With QTL a map/set will always insert anew, even if the key already exists, but STL won't, also the STL `at()` method will throw if the key does not exist (but not in QTL, as they are not allowed to throw), there may be other examples. – user1095108 Jun 26 '14 at 13:52
  • 2
    @SaZ: `QList` is advertised as a "good default container", but if inserting doubles causes a heap allocation, then it isn't. And yes, `QVector` is better, but not as good as `std::vector`, d/t the additional indirection through the d-pointer. It also detaches in surprising places (non-const `begin()`) and doesn't detach in equally surprising cases (try storing an iterator of a `QList`, take a copy of the `QList`, modify the element through the stored iterator and guess what happens to the copy...:o ) – Marc Mutz - mmutz Dec 01 '14 at 11:58
  • @MarcMutz-mmutz `QVector` is good documented, and it is a Qt container. So you should not compare it's methods with `std::vector`. – Dmitry Sazonov Dec 01 '14 at 13:39
  • @SaZ: Sorry, your comment makes no sense to me... It seems you're saying that it's somehow forbidden to compare `QVector` and `std::vector`? Why? Obviously, I disagree, and, more importantly: You're years too late: http://marcmutz.wordpress.com/effective-qt/containers/ – Marc Mutz - mmutz Dec 01 '14 at 13:45
  • @user1095108: Qt containers throw in *exactly* the same circumstances as the STL containers (assuming the allocator doesn't throw on copying/moving): If memory allocation fails or if an operation on the `value_type` fails. The only exception is `at()`. It is provided precisely for *when* you want range checking. If you don't want it, don't use it. BTW: Qt's `at()` *asserts* when out-of-range. That's better? – Marc Mutz - mmutz Feb 11 '15 at 13:58
  • 1
    @MarcMutz-mmutz You are wrong. Exceptions can be disabled in QT (`CONFIG -= exceptions`), also, for strictness, an insert into a `QMap` containing the same key already succeeds, while it does not succeed for a `std::map` (as far as I remember, don't use Q-containers anymore). Their various idiosyncrasies bit me time and again, until I've stopped using them. – user1095108 Feb 11 '15 at 14:23
  • @user1095108: a) QtCore is currently compiled with exceptions enabled. b) even if it isn't, `QVector` is fully inline, so if you disable exceptions in the project _using_ it, they won't throw exceptions (but then neither will `std::vector`). My point is: it's not the container that throws exceptions. Containers are exception-neutral, they just let exception thrown elsewhere pass through. Except that `QVector` isn't exception-safe and may leak resources when an exception passes through its code. – Marc Mutz - mmutz Feb 11 '15 at 14:30
  • 2
    "Some STL implementations are especially bad." Do you have examples of which ones? – Stefan Mar 30 '15 at 08:03
73

The Qt containers are more limited than the STL ones. A few examples of where the STL ones are superior (all of these I have hit in the past):

  • STL is standardized, doesn't change with every Qt version (Qt 2 had QList (pointer-based) and QValueList (value-based); Qt 3 had QPtrList and QValueList; Qt 4 now has QList, and it's nothing at all like QPtrList or QValueList). Qt 6 will have a QList that's QVector while QVector will be deprecated. Even if you end up using the Qt containers, use the STL-compatible API subset (ie. push_back(), not append(); front(), not first(), ...) to avoid porting yet again come Qt 6. In both Qt2->3 and Qt3->4 transitions, the changes in the Qt containers were among those requiring the most code churn. I expect the same for Qt5->6.
  • STL bidirectional containers all have rbegin()/rend(), making reverse iteration symmetric to forward iteration. Not all Qt containers have them (the associative ones don't), so reverse iteration is needlessly complicated.
  • STL containers have range-insert() from different, but compatible, iterator types, making std::copy() much less often needed.
  • STL containers have an Allocator template argument, making custom memory management trivial (typedef required), compared with Qt (fork of QLineEdit required for s/QString/secqstring/). EDIT 20171220: This cuts Qt off of advances in allocator design following C++11 and C++17, cf. e.g. John Lakos' talk (part 2).
  • There's no Qt equivalent to std::deque.
  • std::list has splice(). Whenever I find myself using std::list, it's because I need splice().
  • std::stack, std::queue properly aggregate their underlying container, and don't inherit it, as QStack, QQueue do.
  • QSet is like std::unordered_set, not like std::set.
  • QList is a just weird.

Many of the above could be solved quite easily in Qt, but the container library in Qt seems to experience a lack of development focus at the moment.

EDIT 20150106: After having spent some time trying to bring C++11-support to Qt 5 container classes, I have decided that it's not worth the work. If you look at the work that is being put into C++ standard library implementations, it's quite clear that the Qt classes will never catch up. We've released Qt 5.4 now and QVector still doesn't move elements on reallocations, doesn't have emplace_back() or rvalue-push_back()... We also recently rejected a QOptional class template, waiting for std::optional instead. Likewise for std::unique_ptr. I hope that trend continues.

EDIT 20201009: Come Qt 6, they will again rewrite their containers in incompatible ways:

  • QVector will be renamed QList, so you lose stabiliy-of-reference when using QList.
  • QVector (the name) will be deprecated. QLinkedList will be removed.
  • QHash and QSet are now Open-Addressing Hash Tables, also losing stability-of-reference guarantees
  • QMap will be backed by std::map, possibly changing insertion behaviour and, for QMultiMap, order of equivalent elements.
  • Qt container sizes and indexes will become qsizetype (more or less std::ptrdiff_t) (was: int).

So, if you want to rewrite your container-using code, then go ahead with the Qt containers. Everyone else enjoys decades of stability with the STL containers.

Marc Mutz - mmutz
  • 22,883
  • 10
  • 72
  • 86
  • 3
    Huh. I was under the impression `QList` *was* the equivalent to `std::deque`. Clearly, I shouldn't have just skimmed the documentation. – Dennis Zickefoose May 03 '11 at 06:17
  • `QVector` has had `crbegin` and friends since Qt 5.6 – Bart Louwers Dec 16 '17 at 21:31
  • @Alex: right, I added the easy ones, but not all of the Qt containers have them, yet (because you don't use `std::reverse_iterator` over the broken `QHash`/`QMap` iterators, which, when dereferenced, return `mapped_type` instead of `value_type`). Nothing that cannot be fixed, but see my ***EDIT*** from 2015. – Marc Mutz - mmutz Dec 20 '17 at 13:03
  • @MarcMutz-mmutz Thank you for clarifying. – Bart Louwers Dec 23 '17 at 16:25
  • 2
    May be worth adding to the list the fact that e.g. `QVector` uses `int` as its index, thus limiting 31-bit sizes (even on 64-bit systems). Moreover, it can't even store `INT_MAX` elements of size larger than 1 byte. E.g. the largest `.size()` I could have of `QVector` on x86_64 Linux gcc was 536870907 elements (2²⁹-5), while `std::vector` successfully allocated 4294967295 elements (2³²-1; didn't try more due to lack of RAM for this (this size already takes 16 GiB)). – Ruslan Oct 16 '19 at 13:20
  • `std::unordered_set` is just weird – Kiruahxh Oct 16 '20 at 12:23
35

Let's break down these claims into actual measurable phenomena:

  • Lighter: Qt containers use less memory than STL containers
  • Safer: Qt containers have less opportunity to be improperly used
  • Easier: Qt containers present less of an intellectual burden

Easier

The claim made in this context is that java-style iteration is somehow "easier" than STL style, and therefore Qt is easier to use because of this additional interface.

Java Style:

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

STL Style:

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

The Java iterator style has the benefit of being a little smaller and cleaner. The problem is, this isn't actually STL style anymore.

C++11 STL Style

for( auto i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

or

C++11 foreach style

for (QString i : list)
    qDebug << i;

Which is so drastically simple that there's no reason to ever use anything else (unless you don't support C++11).

My favorite, however, is:

BOOST_FOREACH(QString i, list)
{
    qDebug << i;
}

So, as we can see, this interface gains us nothing except an additional interface, on top of an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".

Also, Qt foreach and java interfaces add overhead; they copy the structure, and provide an unnecessary level of indirection. This might not seem like much, but why add a layer of overhead to provide a not-that-much-simpler interface? Java has this interface because java doesn't have operator overloading; C++ does.

Safer

The justification that Qt gives is the implicit sharing problem, which is neither implicit nor a problem. It does involve sharing, however.

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/

First, this isn't implicit; you are explicitly assigning one vector to another. The STL iterator specification clearly indicates that iterators belong to the container, so we've clearly introduced a shared container between b and a. Second, this isn't a problem; as long as all the rules of the iterator specification are followed, absolutely nothing will go wrong. The only time something goes wrong is here:

b.clear(); // Now the iterator i is completely invalid.

Qt specifies this as if it means something, like a problem arises de novo from this scenario. It doesn't. The iterator is invalidated, and just like anything that can be accessed from multiple disjoint areas, this is just how it works. In fact, this will occur readily with Java style iterators in Qt, thanks to it's heavily reliance on implicit sharing, which is an antipattern as documented here, and at many other areas. It seems especially strange for this "optimization" to be put into use in a framework moving more and more towards multithreading, but that's marketing for you.

Lighter

This one is a bit trickier. The use of Copy-On-Write and Implicit Sharing and Growth Strategies makes it very difficult to actually make guarantees about how much memory your container will use at any given time. This is unlike the STL, which gives you strong algorithmic guarantees.

We know the minimal bound of wasted space for a vector is the square root of the length of the vector, but there seems to be no way to implement this in Qt; the various "optimizations" they support would preclude this very important space saving feature. The STL does not require this feature (and most use a doubling growth, which is more wasteful), but it's important to note that you could at least implement this feature, if need be.

The same is true of doubly linked lists, which could use XOr linking to drastically reduce space used. Again, this is impossible with Qt, due to it's requirements for growth and COW.

COW can indeed make something lighter, but so can Intrusive Containers, such as supported by boost, and Qt used these frequently in the earlier versions, but they are not used as much anymore because they are hard to use, unsafe, and impose a burden on the programmer. COW is a much less intrusive solution, but unattractive for the reasons posed above.

There is no reason why you could not use STL containers with the same memory cost or less than Qt's containers, with the added benefit of actually knowing how much memory you will waste at any given time. It is, unfortunately, impossible to compare the two in raw memory usage, because such benchmarks would show wildly different results in different use cases, which is the exact sort of problem that the STL was designed to correct.

In Conclusion

Avoid use of Qt Containers when ever possible to do so without imposing a copying cost, and use STL type iteration (perhaps through a wrapper or the new syntax), whenever possible.

Community
  • 1
  • 1
Alice
  • 3,822
  • 2
  • 22
  • 28
  • 4
    Your points are largely valid, but there is some misleading info in there: `Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".` Qt's Java-style iterators weren't added onto C++11; they predate it. Anyway Qt's `foreach(QString elem, list)` is just as easy as C++11's foreach or BOOST_FOREACH and it works with pre-C++11 compliant compilers. – weberc2 Jun 25 '14 at 16:05
  • @weberc2 You are confused; Qt's Java style iterators are added on top of C++ (not C++11) iterators. It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier. And foreach for Qt is not as easy as BOOST_FOREACH, as it is notably not as safe, and does not have the same breadth of support (BOOST_FOREACH can apply to any range, for any version of C++, where as foreach in QT demands C++03 compliance). QT's foreach should be avoided at all costs. – Alice Jun 25 '14 at 21:01
  • `So, as we can see, this interface gains us nothing except an additional interface, *on top of* an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".` (emphasis mine) You said this right after you showed us C++11 and BOOST versions of foreach, making it sound like the Qt version is built off of one of those two, which is not the case AFAICT. I'm sure that's not what you meant, but that's how it comes off. Hence "misleading information". – weberc2 Jun 25 '14 at 21:13
  • `It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.` It's still unclear what you're comparing against. C++03 iterators? C++11 iterators? BOOST_FOREACH? All of the above? – weberc2 Jun 25 '14 at 21:17
  • `And foreach for Qt is not as easy as BOOST_FOREACH, as it is notably not as safe, and does not have the same breadth of support (BOOST_FOREACH can apply to any range, for any version of C++, where as foreach in QT demands C++03 compliance)` I stand corrected. – weberc2 Jun 25 '14 at 21:18
  • @weberc2 C++ iterators, as a general construction, haven't changed much since the STL was standardized (C++98, with the exception of loosening restrictions and SCARY iterators). So I don't think my language is unreasonable; shimming Java style iterators (which exist because of various Java design choices) into C++ which already has a competent (and faster) iterator design is unnecessary and confusing (and therefore not easier). QT tries to say they are "safer", but C++ iterators are not unsafe, so this isn't a very good reason. – Alice Jun 28 '14 at 11:33
  • 1
    I'm just saying, you're often very ambiguous as to which iteration method you're referring. I believe that you think you're clear and your language is reasonable, but it seems strange to refuse to specify. Agree to disagree, I suppose. – weberc2 Jul 01 '14 at 17:26
  • I wonder, if this comparison still holds basically true as of 2020. Also, would be interesting to learn about the `sizeof` difference. E.g., on my platform, `sizeof(std::string)` is 32, while `sizeof(QString)` is only 8. It's not obvious, though, how it might affect performance. P.S. In fact, all Qt containers seem to have size equal 8, even `QMap`, while `std::map` is 48 bytes. – Maximko Jul 22 '20 at 14:56
  • 2
    @Maximko that's because they use the pimpl idiom – Waqar Sep 11 '20 at 13:45
  • Some std containers are largely useless (map / unordered_map) etc because they are so terrible performance wise. Also, in GUI code it would result in worse performance if you use standard containers because you would have to convert them back and forth. – Waqar Sep 11 '20 at 13:49
24

STL containers:

  • Have performance guarantees
  • Can be used in STL algorithms which also have performance guarantees
  • Can be leveraged by third-party C++ libraries like Boost
  • Are standard, and likely to outlive proprietary solutions
  • Encourage generic programming of algorithms and data structures. If you write new algorithms and data structures that conform to STL you can leverage what STL already provides at no cost.
fbrereto
  • 34,250
  • 17
  • 118
  • 176
  • 6
    All of the above except being a standard are true for the QTL also, provided that you compile Qt with STL support (the default). STL support includes iterator functions, container typedefs (const_iterator, etc), conversion functions (to/from STL). – rpg Nov 03 '09 at 21:50
  • 4
    @rpg Almost all of them are not true of QTL; QTL has no strong performance guarantees (as they readily have broke them in the past), are not STL compliant (no reverse, and thus cannot be used by much of boost), are not standard (they change constantly between versions), and do not encourage generic programming (they have no template arguments for allocators, for example). – Alice May 24 '14 at 15:58
  • This answer is mostly obsolete and partially incorrect. – Waqar Sep 11 '20 at 13:52
  • STL is slooooooow. CopperSpice is a fork of Qt 4.8 that replaced the underlying containers with STL containers. They got rid of CoW. I was attempting to port Gede debugger GUI from Qt to CopperSpice. Pull these to examples down and see for yourself. https://www.logikalsolutions.com/wordpress/information-technology/qlist/ – user3450148 Feb 28 '21 at 13:24
15

Qt containers use copy-on-write idiom.

TimW
  • 8,075
  • 1
  • 27
  • 32
  • 2
    +1, might be a significant advantage in performance and resource – RedGlyph Nov 03 '09 at 16:10
  • 33
    Or might be a significant disadvantage. See http://www.gotw.ca/publications/optimizations.htm – Kaz Dragon Nov 03 '09 at 16:23
  • 3
    The atomic refcount seems to fare pretty well: http://labs.trolltech.com/blogs/2006/10/16/atomic-reference-counting-is-it-worth-it-2/ – rpg Nov 03 '09 at 21:52
  • STL containers are free to use whatever idioms exist as long as they meet their performance guarantees and the spec. COW is valid, even under C++11/C++14 STL. – Alice May 24 '14 at 15:59
  • 1
    @Alice COW is not a valid implementation most of the time because it breaks standard's complexity and iterator validity guarantees in almost any case. One of the few classes that could be implemented with COW was `std::basic_string` and the standard took actions with C++11 to make this non-conformant. – Tiago Gomes May 27 '14 at 14:06
  • @TiagoGomes That's not true; naive implementations break complexity, but this in no way means all possible ones can or will break those guarantees. – Alice May 27 '14 at 16:44
  • @Alice I can't argue about the complexity guarantees as I apparently only know naive implementations. Would you mind linking me to an implementation that would obey every complexity guarantee by the standard ? I would truly appreciate it. But talking about iterator validity, I don't think there is a way of implementing COW and preserve guarantees. (This is why gcc is dropping COW on `std::basic_string`) – Tiago Gomes May 27 '14 at 19:03
9

One of the main issues is that Qt's API expects you to provide data in Qt's containers, so you may as well simply use the Qt containers rather than transforming back and forth between the two.

Also, if you're already using the Qt containers, it might be slightly more optimal to use them exclusively, as you would not have to include the STL header files and potentially link in the STL libraries. However, depending on your toolchain, that may happen anyway. Purely from a design perspective, consistency is generally a good thing.

qid
  • 1,793
  • 9
  • 13
  • 1
    The rate at which you have to "transform back and forth" between STL and Qt containers in a real application that uses STL except where interfacing with Qt is generally greatly overestimated. Most of the time you do some std::transform coming to/from the presentation layer (which uses Qt) and you get the container switch for free. Interested parties may browse over to https://projects.kde.org/projects/kde/kdepim/repository/revisions/master/show/kleopatra to see for themselves. – Marc Mutz - mmutz Feb 11 '15 at 14:05
8

If the data you are working with is mostly used to drive the Qt based UI, then definitely use Qt containers.

If the data is mostly used internally in the app, and you're never likely to port away from Qt, then barring performance issues, use the Qt containers because it will make the bits of data that go to the UI easier to deal with.

If the data is mostly used in conjunction with other libraries that only know about STL containers, then use STL containers. If you have this situation you're in trouble no matter what because you're going to do a lot of porting back and forth between container types no matter what you do.

Michael Kohne
  • 11,516
  • 3
  • 43
  • 71
6

Besides the COW difference, STL containers are much more widely supported on a variety of platforms. Qt is portable enough if you limit your work to "mainstream" platforms, but the STL is available on many other more obscure platforms too (e.g., Texas Instruments' DSPs).

Because the STL is standard rather than controlled by a single corporation, there are, generally speaking, more programmers who can easily read, understand, and modify STL code and more resources (books, online forums, conferences, etc.) to support them in doing this than there are for Qt. That's not to say that one should shy away from Qt for this reason alone; just that, all other things being equal, you should default to the STL, but of course all things are rarely equal, so you'll have to decide in your own context which makes the most sense.

In regard to AlexKR's answer: the STL performance is guaranteed within limits, but a given implementation may make use of platform-dependent details to speed up their STL. So in that sense, you may get different results on different platforms, but it will never be slower than the explicit guarantee (modulo bugs).

metal
  • 5,609
  • 30
  • 44
  • 9
    With regards to your first point: I assume the OP is referring to projects that already use Qt, and are therefore already limited to "mainstream" platforms. It seems unlikely that someone would pull in such a heavyweight library as Qt just for its container classes. – ThisSuitIsBlackNot Nov 03 '09 at 17:23
4

My five cents: Qt containers are supposed to work similar on different platforms. While STL containers depend on STL implementation. You might get different performance results.

EDIT: I am not telling that STL is "slower" but I point to effects of various implementation details.
Please check this, and then maybe this.
And it is not a real problem of STL. Obviosly, if you have significant difference in performance, then there is problem in the code which uses STL.

Community
  • 1
  • 1
alexkr
  • 4,405
  • 1
  • 21
  • 20
  • STL containers are all similar, irrespective of the implementation. You can't have a vector implemented like a list behind the scenes as it has to be in a contiguous block of memory. The STL is also usually optimized to huge extents on all major platforms. – Yacoby Nov 03 '09 at 16:19
  • 1
    If you stick to what the STL promises (instead of assuming how it's implemented) you'll never have a problem moving between platforms with STL. Same with Qt. – Michael Kohne Nov 03 '09 at 21:25
  • This is the exact opposite of true. STL containers always work the same on all platforms; if they don't, they aren't STL. QT, however, drastically changes performance from version to version, so on a platform with QT4.0 rather than QT4.8, you can get some serious changes. – Alice May 24 '14 at 16:00
  • 1
    You are confusing two very different types of performance; algorithmic performance and practical computational performance. All STL implementations guarantee the same algorithmic performance; if your vector takes log(n) time to index an element, it isn't an STL vector. Your links point to practical computational performance, which is meaningless in this discussion; QT changes their algorithms between versions, and the same C++ on different platforms gets different performance. These are, in my experience, far more malleable than differences in STL performance. – Alice May 28 '14 at 18:31
3

I guess it depends on the way you use Qt. If you use it all over your product, than it probably makes sense to use Qt containers. If you contain it only to (for instance) the UI portion, it may be better to use C++ standard containers.

Nemanja Trifunovic
  • 23,597
  • 3
  • 46
  • 84
3

I am of the opinion that STL is a excellent piece of software however if I am to do some KDE or Qt related programming then Qt is the way to go. Also it depends on the compiler you are using, with GCC STL works pretty good however if you have to use say SUN Studio CC then STL will most likely bring you headaches because of the compiler not the STL per se. In that case since the compiler will make your head hurt just use Qt to save you the trouble. Just my 2 cents...

Paulo Lopes
  • 5,322
  • 20
  • 29
3

There is a (sometimes) big limitation in QVector. It can only allocate int bytes of memory (note that the limit is in bytes not in number of elements). This implies that trying to allocate contiguous blocks of memory bigger than ~2GB with a QVector will lead to a crash. This happens with Qt 4 and 5. std::vector does not have such limitation.

fedemp
  • 190
  • 4
0

The main reason to go with STL containers for me is if you need a custom allocator in order to reuse memory in very big containers. Suppose for example that you have a QMap that stores 1000000 entries (key/value pairs). In Qt that implies exactly 1000000 million allocations (new calls) no matter what. In STL you can always create a custom allocator that internally allocates all that memory at once and assign it to each entry as the map is populated.

My advice is to use STL containers when writing performance critical algorithms in the business logic and then convert them back to Qt containers when the results are ready to by displayed by your UI controls and forms if needed.

Darien Pardinas
  • 5,176
  • 1
  • 32
  • 43