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);
QVector<int>::iterator i = a.begin();
b = a;
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();
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.