566 lines
24 KiB
Plaintext
566 lines
24 KiB
Plaintext
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
|
|
|
/*!
|
|
\page containers.html
|
|
\title Container Classes
|
|
\ingroup groups
|
|
\ingroup qt-basic-concepts
|
|
\keyword container class
|
|
\keyword container classes
|
|
|
|
\brief Qt's template-based container classes.
|
|
|
|
\tableofcontents
|
|
|
|
\section1 Introduction
|
|
|
|
The Qt library provides a set of general purpose template-based
|
|
container classes. These classes can be used to store items of a
|
|
specified type. For example, if you need a resizable array of
|
|
\l{QString}s, use QList<QString>.
|
|
|
|
These container classes are designed to be lighter, safer, and
|
|
easier to use than the STL containers. If you are unfamiliar with
|
|
the STL, or prefer to do things the "Qt way", you can use these
|
|
classes instead of the STL classes.
|
|
|
|
The container classes are \l{implicitly shared}, they are
|
|
\l{reentrant}, and they are optimized for speed, low memory
|
|
consumption, and minimal inline code expansion, resulting in
|
|
smaller executables. In addition, they are \l{thread-safe}
|
|
in situations where they are used as read-only containers
|
|
by all threads used to access them.
|
|
|
|
The containers provide iterators for traversal. \l{STL-style iterators}
|
|
are the most efficient ones and can be used together with Qt's and
|
|
STL's \l{generic algorithms}.
|
|
\l{Java-style Iterators} are provided for backwards compatibility.
|
|
|
|
\note Since Qt 5.14, range constructors are available for most of the
|
|
container classes. QMultiMap is a notable exception. Their use is
|
|
encouraged in place of the various from/to methods. For example:
|
|
|
|
\snippet code/doc_src_containers.cpp 25
|
|
|
|
\section1 The Container Classes
|
|
|
|
Qt provides the following sequential containers: QList,
|
|
QStack, and QQueue. For most
|
|
applications, QList is the best type to use. It provides very fast
|
|
appends. If you really need a linked-list, use std::list.
|
|
QStack and QQueue are convenience classes that provide LIFO and
|
|
FIFO semantics.
|
|
|
|
Qt also provides these associative containers: QMap,
|
|
QMultiMap, QHash, QMultiHash, and QSet. The "Multi" containers
|
|
conveniently support multiple values associated with a single
|
|
key. The "Hash" containers provide faster lookup by using a hash
|
|
function instead of a binary search on a sorted set.
|
|
|
|
As special cases, the QCache and QContiguousCache classes provide
|
|
efficient hash-lookup of objects in a limited cache storage.
|
|
|
|
\table
|
|
\header \li Class \li Summary
|
|
|
|
\row \li \l{QList}<T>
|
|
\li This is by far the most commonly used container class. It
|
|
stores a list of values of a given type (T) that can be accessed
|
|
by index. Internally, it stores an array of values of a
|
|
given type at adjacent
|
|
positions in memory. Inserting at the front or in the middle of
|
|
a list can be quite slow, because it can lead to large numbers
|
|
of items having to be moved by one position in memory.
|
|
|
|
\row \li \l{QVarLengthArray}<T, Prealloc>
|
|
\li This provides a low-level variable-length array. It can be used
|
|
instead of QList in places where speed is particularly important.
|
|
|
|
\row \li \l{QStack}<T>
|
|
\li This is a convenience subclass of QList that provides
|
|
"last in, first out" (LIFO) semantics. It adds the following
|
|
functions to those already present in QList:
|
|
\l{QStack::push()}{push()}, \l{QStack::pop()}{pop()},
|
|
and \l{QStack::top()}{top()}.
|
|
|
|
\row \li \l{QQueue}<T>
|
|
\li This is a convenience subclass of QList that provides
|
|
"first in, first out" (FIFO) semantics. It adds the following
|
|
functions to those already present in QList:
|
|
\l{QQueue::enqueue()}{enqueue()},
|
|
\l{QQueue::dequeue()}{dequeue()}, and \l{QQueue::head()}{head()}.
|
|
|
|
\row \li \l{QSet}<T>
|
|
\li This provides a single-valued mathematical set with fast
|
|
lookups.
|
|
|
|
\row \li \l{QMap}<Key, T>
|
|
\li This provides a dictionary (associative array) that maps keys
|
|
of type Key to values of type T. Normally each key is associated
|
|
with a single value. QMap stores its data in Key order; if order
|
|
doesn't matter QHash is a faster alternative.
|
|
|
|
\row \li \l{QMultiMap}<Key, T>
|
|
\li This is a convenience subclass of QMap that provides a nice
|
|
interface for multi-valued maps, i.e. maps where one key can be
|
|
associated with multiple values.
|
|
|
|
\row \li \l{QHash}<Key, T>
|
|
\li This has almost the same API as QMap, but provides
|
|
significantly faster lookups. QHash stores its data in an
|
|
arbitrary order.
|
|
|
|
\row \li \l{QMultiHash}<Key, T>
|
|
\li This is a convenience subclass of QHash that
|
|
provides a nice interface for multi-valued hashes.
|
|
|
|
\endtable
|
|
|
|
Containers can be nested. For example, it is perfectly possible
|
|
to use a QMap<QString, QList<int>>, where the key type is
|
|
QString and the value type QList<int>.
|
|
|
|
The containers are defined in individual header files with the
|
|
same name as the container (e.g., \c <QList>). For
|
|
convenience, the containers are forward declared in \c
|
|
<QtContainerFwd>.
|
|
|
|
\target assignable data type
|
|
\target assignable data types
|
|
|
|
The values stored in the various containers can be of any
|
|
\e{assignable data type}. To qualify, a type must provide a
|
|
copy constructor, and an assignment operator. For some
|
|
operations a default constructor is also required. This
|
|
covers most data types you are likely to want to
|
|
store in a container, including basic types such as \c int and \c
|
|
double, pointer types, and Qt data types such as QString, QDate,
|
|
and QTime, but it doesn't cover QObject or any QObject subclass
|
|
(QWidget, QDialog, QTimer, etc.). If you attempt to instantiate a
|
|
QList<QWidget>, the compiler will complain that QWidget's copy
|
|
constructor and assignment operators are disabled. If you want to
|
|
store these kinds of objects in a container, store them as
|
|
pointers, for example as QList<QWidget *>.
|
|
|
|
Here's an example custom data type that meets the requirement of
|
|
an assignable data type:
|
|
|
|
\snippet code/doc_src_containers.cpp 0
|
|
|
|
If we don't provide a copy constructor or an assignment operator,
|
|
C++ provides a default implementation that performs a
|
|
member-by-member copy. In the example above, that would have been
|
|
sufficient. Also, if you don't provide any constructors, C++
|
|
provides a default constructor that initializes its member using
|
|
default constructors. Although it doesn't provide any
|
|
explicit constructors or assignment operator, the following data
|
|
type can be stored in a container:
|
|
|
|
\snippet streaming/main.cpp 0
|
|
|
|
Some containers have additional requirements for the data types
|
|
they can store. For example, the Key type of a QMap<Key, T> must
|
|
provide \c operator<(). Such special requirements are documented
|
|
in a class's detailed description. In some cases, specific
|
|
functions have special requirements; these are described on a
|
|
per-function basis. The compiler will always emit an error if a
|
|
requirement isn't met.
|
|
|
|
Qt's containers provide operator<<() and operator>>() so that they
|
|
can easily be read and written using a QDataStream. This means
|
|
that the data types stored in the container must also support
|
|
operator<<() and operator>>(). Providing such support is
|
|
straightforward; here's how we could do it for the Movie struct
|
|
above:
|
|
|
|
\snippet streaming/main.cpp 1
|
|
\codeline
|
|
\snippet streaming/main.cpp 2
|
|
|
|
\target default-constructed value
|
|
|
|
The documentation of certain container class functions refer to
|
|
\e{default-constructed values}; for example, QList
|
|
automatically initializes its items with default-constructed
|
|
values, and QMap::value() returns a default-constructed value if
|
|
the specified key isn't in the map. For most value types, this
|
|
simply means that a value is created using the default
|
|
constructor (e.g. an empty string for QString). But for primitive
|
|
types like \c{int} and \c{double}, as well as for pointer types,
|
|
the C++ language doesn't specify any initialization; in those
|
|
cases, Qt's containers automatically initialize the value to 0.
|
|
|
|
\section1 The Iterator Classes
|
|
|
|
Iterators provide a uniform means to access items in a container.
|
|
Qt's container classes provide two types of iterators: STL-style
|
|
iterators and Java-style iterators. Iterators of both types are
|
|
invalidated when the data in the container is modified or detached
|
|
from \l{Implicit Sharing}{implicitly shared copies} due to a call
|
|
to a non-const member function.
|
|
|
|
\section2 STL-Style Iterators
|
|
|
|
STL-style iterators have been available since the release of Qt
|
|
2.0. They are compatible with Qt's and STL's \l{generic
|
|
algorithms} and are optimized for speed.
|
|
|
|
For each container class, there are two STL-style iterator types:
|
|
one that provides read-only access and one that provides
|
|
read-write access. Read-only iterators should be used wherever
|
|
possible because they are faster than read-write iterators.
|
|
|
|
\table
|
|
\header \li Containers \li Read-only iterator
|
|
\li Read-write iterator
|
|
\row \li QList<T>, QStack<T>, QQueue<T> \li QList<T>::const_iterator
|
|
\li QList<T>::iterator
|
|
\row \li QSet<T> \li QSet<T>::const_iterator
|
|
\li QSet<T>::iterator
|
|
\row \li QMap<Key, T>, QMultiMap<Key, T> \li QMap<Key, T>::const_iterator
|
|
\li QMap<Key, T>::iterator
|
|
\row \li QHash<Key, T>, QMultiHash<Key, T> \li QHash<Key, T>::const_iterator
|
|
\li QHash<Key, T>::iterator
|
|
\endtable
|
|
|
|
The API of the STL iterators is modelled on pointers in an array.
|
|
For example, the \c ++ operator advances the iterator to the next
|
|
item, and the \c * operator returns the item that the iterator
|
|
points to. In fact, for QList and QStack, which store their
|
|
items at adjacent memory positions, the
|
|
\l{QList::iterator}{iterator} type is just a typedef for \c{T *},
|
|
and the \l{QList::iterator}{const_iterator} type is
|
|
just a typedef for \c{const T *}.
|
|
|
|
In this discussion, we will concentrate on QList and QMap. The
|
|
iterator types for QSet have exactly
|
|
the same interface as QList's iterators; similarly, the iterator
|
|
types for QHash have the same interface as QMap's iterators.
|
|
|
|
Here's a typical loop for iterating through all the elements of a
|
|
QList<QString> in order and converting them to lowercase:
|
|
|
|
\snippet code/doc_src_containers.cpp 10
|
|
|
|
STL-style iterators point directly at items. The \l{QList::begin()}{begin()}
|
|
function of a container returns an iterator that points to the first item in the
|
|
container. The \l{QList::end()}{end()} function of a container returns an iterator to the
|
|
imaginary item one position past the last item in the container.
|
|
\l {QList::end()}{end()} marks an invalid position; it must never be dereferenced.
|
|
It is typically used in a loop's break condition. If the list is
|
|
empty, \l{QList::begin}{begin()} equals \l{QList::end()}{end()}, so we never execute the loop.
|
|
|
|
The diagram below shows the valid iterator positions as red
|
|
arrows for a list containing four items:
|
|
|
|
\image stliterators1.png
|
|
|
|
Iterating backward with an STL-style iterator is done with reverse iterators:
|
|
|
|
\snippet code/doc_src_containers.cpp 11
|
|
|
|
In the code snippets so far, we used the unary \c * operator to
|
|
retrieve the item (of type QString) stored at a certain iterator
|
|
position, and we then called QString::toLower() on it. Most C++
|
|
compilers also allow us to write \c{i->toLower()}, but some
|
|
don't.
|
|
|
|
For read-only access, you can use const_iterator, \l{QList::constBegin}{constBegin()},
|
|
and \l{QList::constEnd()}{constEnd()}. For example:
|
|
|
|
\snippet code/doc_src_containers.cpp 12
|
|
|
|
The following table summarizes the STL-style iterators' API:
|
|
|
|
\table
|
|
\header \li Expression \li Behavior
|
|
\row \li \c{*i} \li Returns the current item
|
|
\row \li \c{++i} \li Advances the iterator to the next item
|
|
\row \li \c{i += n} \li Advances the iterator by \c n items
|
|
\row \li \c{--i} \li Moves the iterator back by one item
|
|
\row \li \c{i -= n} \li Moves the iterator back by \c n items
|
|
\row \li \c{i - j} \li Returns the number of items between iterators \c i and \c j
|
|
\endtable
|
|
|
|
The \c{++} and \c{--} operators are available both as prefix
|
|
(\c{++i}, \c{--i}) and postfix (\c{i++}, \c{i--}) operators. The
|
|
prefix versions modify the iterators and return a reference to
|
|
the modified iterator; the postfix versions take a copy of the
|
|
iterator before they modify it, and return that copy. In
|
|
expressions where the return value is ignored, we recommend that
|
|
you use the prefix operators (\c{++i}, \c{--i}), as these are
|
|
slightly faster.
|
|
|
|
For non-const iterator types, the return value of the unary \c{*}
|
|
operator can be used on the left side of the assignment operator.
|
|
|
|
For QMap and QHash, the \c{*} operator returns the value
|
|
component of an item. If you want to retrieve the key, call key()
|
|
on the iterator. For symmetry, the iterator types also provide a
|
|
value() function to retrieve the value. For example, here's how
|
|
we would print all items in a QMap to the console:
|
|
|
|
\snippet code/doc_src_containers.cpp 13
|
|
|
|
Thanks to \l{implicit sharing}, it is very inexpensive for a
|
|
function to return a container per value. The Qt API contains
|
|
dozens of functions that return a QList or QStringList per value
|
|
(e.g., QSplitter::sizes()). If you want to iterate over these
|
|
using an STL iterator, you should always take a copy of the
|
|
container and iterate over the copy. For example:
|
|
|
|
\snippet code/doc_src_containers.cpp 14
|
|
|
|
This problem doesn't occur with functions that return a const or
|
|
non-const reference to a container.
|
|
|
|
\section3 Implicit sharing iterator problem
|
|
|
|
\l{Implicit sharing} has another consequence on STL-style
|
|
iterators: you should avoid copying a container while
|
|
iterators are active on that container. The iterators
|
|
point to an internal structure, and if you copy a container
|
|
you should be very careful with your iterators. E.g:
|
|
|
|
\snippet code/doc_src_containers.cpp 24
|
|
|
|
The above example only shows a problem with QList, but
|
|
the problem exists for all the implicitly shared Qt containers.
|
|
|
|
\section2 Java-Style Iterators
|
|
\l{java-style-iterators}{Java-Style iterators} were introduced in Qt 4. Their API is modelled
|
|
on Java's iterator classes.
|
|
New code should should prefer \l{STL-Style Iterators}.
|
|
|
|
\section1 Qt containers compared with std containers
|
|
|
|
\table
|
|
\header \li Qt container \li Closest std container
|
|
|
|
\row \li \l{QList}<T>
|
|
\li Similar to std::vector<T>
|
|
|
|
\l{QList} and \l{QVector} were unified in Qt 6. Both
|
|
use the datamodel from QVector. QVector is now an alias to QList.
|
|
|
|
This means that QList is not implemented as a linked list, so if
|
|
you need constant time insert, delete, append or prepend,
|
|
consider \c std::list<T>. See \l{QList} for details.
|
|
|
|
\row \li \l{QVarLengthArray}<T, Prealloc>
|
|
\li Resembles a mix of std::array<T> and std::vector<T>.
|
|
|
|
For performance reasons, QVarLengthArray lives on the stack unless
|
|
resized. Resizing it automatically causes it to use the heap instead.
|
|
|
|
\row \li \l{QStack}<T>
|
|
\li Similar to std::stack<T>, inherits from \l{QList}.
|
|
|
|
\row \li \l{QQueue}<T>
|
|
\li Similar to std::queue<T>, inherits from \l{QList}.
|
|
|
|
\row \li \l{QSet}<T>
|
|
\li Similar to std::set<T>. Internally, \l{QSet} is implemented with a
|
|
\l{QHash}.
|
|
|
|
\row \li \l{QMap}<Key, T>
|
|
\li Similar to std::map<T>.
|
|
|
|
\row \li \l{QMultiMap}<Key, T>
|
|
\li Similar to std::multimap<T>.
|
|
|
|
\row \li \l{QHash}<Key, T>
|
|
\li Most similar to std::map<T>.
|
|
|
|
\row \li \l{QMultiHash}<Key, T>
|
|
\li Most similar to std::multimap<T>.
|
|
|
|
\endtable
|
|
|
|
\section1 Qt containers and std algorithms
|
|
|
|
You can use Qt containers with functions from \c{#include <algorithm>}.
|
|
|
|
\snippet code/doc_src_containers.cpp 26
|
|
|
|
\section1 Other Container-Like Classes
|
|
|
|
Qt includes other template classes that resemble containers in
|
|
some respects. These classes don't provide iterators and cannot
|
|
be used with the \l foreach keyword.
|
|
|
|
\list
|
|
\li QCache<Key, T> provides a cache to store objects of a certain
|
|
type T associated with keys of type Key.
|
|
|
|
\li QContiguousCache<T> provides an efficient way of caching data
|
|
that is typically accessed in a contiguous way.
|
|
\endlist
|
|
|
|
Additional non-template types that compete with Qt's template
|
|
containers are QBitArray, QByteArray, QString, and QStringList.
|
|
|
|
\section1 Algorithmic Complexity
|
|
|
|
Algorithmic complexity is concerned about how fast (or slow) each
|
|
function is as the number of items in the container grow. For
|
|
example, inserting an item in the middle of a std::list is an
|
|
extremely fast operation, irrespective of the number of items
|
|
stored in the list. On the other hand, inserting an item
|
|
in the middle of a QList is potentially very expensive if the
|
|
QList contains many items, since half of the items must be
|
|
moved one position in memory.
|
|
|
|
To describe algorithmic complexity, we use the following
|
|
terminology, based on the "big Oh" notation:
|
|
|
|
\target constant time
|
|
\target logarithmic time
|
|
\target linear time
|
|
\target linear-logarithmic time
|
|
\target quadratic time
|
|
|
|
\list
|
|
\li \b{Constant time:} O(1). A function is said to run in constant
|
|
time if it requires the same amount of time no matter how many
|
|
items are present in the container. One example is
|
|
QList::push_back().
|
|
|
|
\li \b{Logarithmic time:} O(log \e n). A function that runs in
|
|
logarithmic time is a function whose running time is
|
|
proportional to the logarithm of the number of items in the
|
|
container. One example is the binary search algorithm.
|
|
|
|
\li \b{Linear time:} O(\e n). A function that runs in linear time
|
|
will execute in a time directly proportional to the number of
|
|
items stored in the container. One example is
|
|
QList::insert().
|
|
|
|
\li \b{Linear-logarithmic time:} O(\e{n} log \e n). A function
|
|
that runs in linear-logarithmic time is asymptotically slower
|
|
than a linear-time function, but faster than a quadratic-time
|
|
function.
|
|
|
|
\li \b{Quadratic time:} O(\e{n}\unicode{178}). A quadratic-time function
|
|
executes in a time that is proportional to the square of the
|
|
number of items stored in the container.
|
|
\endlist
|
|
|
|
The following table summarizes the algorithmic complexity of the sequential
|
|
container QList<T>:
|
|
|
|
\table
|
|
\header \li \li Index lookup \li Insertion \li Prepending \li Appending
|
|
\row \li QList<T> \li O(1) \li O(n) \li O(n) \li Amort. O(1)
|
|
\endtable
|
|
|
|
In the table, "Amort." stands for "amortized behavior". For
|
|
example, "Amort. O(1)" means that if you call the function
|
|
only once, you might get O(\e n) behavior, but if you call it
|
|
multiple times (e.g., \e n times), the average behavior will be
|
|
O(1).
|
|
|
|
The following table summarizes the algorithmic complexity of Qt's
|
|
associative containers and sets:
|
|
|
|
\table
|
|
\header \li{1,2} \li{2,1} Key lookup \li{2,1} Insertion
|
|
\header \li Average \li Worst case \li Average \li Worst case
|
|
\row \li QMap<Key, T> \li O(log \e n) \li O(log \e n) \li O(log \e n) \li O(log \e n)
|
|
\row \li QMultiMap<Key, T> \li O(log \e n) \li O(log \e n) \li O(log \e n) \li O(log \e n)
|
|
\row \li QHash<Key, T> \li Amort. O(1) \li O(\e n) \li Amort. O(1) \li O(\e n)
|
|
\row \li QSet<Key> \li Amort. O(1) \li O(\e n) \li Amort. O(1) \li O(\e n)
|
|
\endtable
|
|
|
|
With QList, QHash, and QSet, the performance of appending items
|
|
is amortized O(log \e n). It can be brought down to O(1) by
|
|
calling QList::reserve(), QHash::reserve(), or QSet::reserve()
|
|
with the expected number of items before you insert the items.
|
|
The next section discusses this topic in more depth.
|
|
|
|
\section1 Optimizations for Primitive and Relocatable Types
|
|
|
|
Qt containers can use optimized code paths if the stored
|
|
elements are relocatable or even primitive.
|
|
However, whether types are primitive or relocatable
|
|
cannot be detected in all cases.
|
|
You can declare your types to be primitive or relocatable
|
|
by using the Q_DECLARE_TYPEINFO macro with the Q_PRIMITIVE_TYPE
|
|
flag or the Q_RELOCATABLE_TYPE flag. See the documentation
|
|
of Q_DECLARE_TYPEINFO for further details and usage examples.
|
|
|
|
If you do not use Q_DECLARE_TYPEINFO,
|
|
Qt will use
|
|
\l {https://en.cppreference.com/w/cpp/types/is_trivial} {std::is_trivial_v<T>}
|
|
to identify primitive
|
|
types and it will require both
|
|
\l {https://en.cppreference.com/w/cpp/types/is_trivially_copyable} {std::is_trivially_copyable_v<T>}
|
|
and
|
|
\l {https://en.cppreference.com/w/cpp/types/is_destructible} {std::is_trivially_destructible_v<T>}
|
|
to identify relocatable types.
|
|
This is always a safe choice, albeit
|
|
of maybe suboptimal performance.
|
|
|
|
\section1 Growth Strategies
|
|
|
|
QList<T>, QString, and QByteArray store their items
|
|
contiguously in memory; QHash<Key, T> keeps a
|
|
hash table whose size is proportional to the number
|
|
of items in the hash. To avoid reallocating the data every single
|
|
time an item is added at the end of the container, these classes
|
|
typically allocate more memory than necessary.
|
|
|
|
Consider the following code, which builds a QString from another
|
|
QString:
|
|
|
|
\snippet code/doc_src_containers.cpp 23
|
|
|
|
We build the string \c out dynamically by appending one character
|
|
to it at a time. Let's assume that we append 15000 characters to
|
|
the QString string. Then the following 11 reallocations (out of a
|
|
possible 15000) occur when QString runs out of space: 8, 24, 56,
|
|
120, 248, 504, 1016, 2040, 4088, 8184, 16376.
|
|
At the end, the QString has 16376 Unicode
|
|
characters allocated, 15000 of which are occupied.
|
|
|
|
The values above may seem a bit strange, but there is a guiding
|
|
principle. It advances by doubling the size each time.
|
|
More precisely, it advances to the next power of two, minus
|
|
16 bytes. 16 bytes corresponds to eight characters, as QString
|
|
uses UTF-16 internally.
|
|
|
|
QByteArray uses the same algorithm as
|
|
QString, but 16 bytes correspond to 16 characters.
|
|
|
|
QList<T> also uses that algorithm, but 16 bytes correspond to
|
|
16/sizeof(T) elements.
|
|
|
|
QHash<Key, T> is a totally different case. QHash's internal hash
|
|
table grows by powers of two, and each time it grows, the items
|
|
are relocated in a new bucket, computed as qHash(\e key) %
|
|
QHash::capacity() (the number of buckets). This remark applies to
|
|
QSet<T> and QCache<Key, T> as well.
|
|
|
|
For most applications, the default growing algorithm provided by
|
|
Qt does the trick. If you need more control, QList<T>,
|
|
QHash<Key, T>, QSet<T>, QString, and QByteArray provide a trio of
|
|
functions that allow you to check and specify how much memory to
|
|
use to store the items:
|
|
|
|
\list
|
|
\li \l{QString::capacity()}{capacity()} returns the
|
|
number of items for which memory is allocated (for QHash and
|
|
QSet, the number of buckets in the hash table).
|
|
\li \l{QString::reserve()}{reserve}(\e size) explicitly
|
|
preallocates memory for \e size items.
|
|
\li \l{QString::squeeze()}{squeeze()} frees any memory
|
|
not required to store the items.
|
|
\endlist
|
|
|
|
If you know approximately how many items you will store in a
|
|
container, you can start by calling \l{QString::reserve()}{reserve()}, and when you are
|
|
done populating the container, you can call \l{QString::squeeze()}{squeeze()} to release
|
|
the extra preallocated memory.
|
|
*/
|