Improve implicit shared documentation a bit

Task-number: QTBUG-27061

Change-Id: I66e000a9f59fda3654066013e6e78c3ba6fd27fe
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thorbjørn Martsum 2013-09-24 16:42:22 +02:00 committed by The Qt Project
parent cfb717d654
commit 499957eb8b
9 changed files with 114 additions and 18 deletions

View File

@ -273,3 +273,33 @@ QString onlyLetters(const QString &in)
return out;
}
//! [23]
//! [24]
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.
*/
a[0] = 5;
/*
Container a is now detached from the shared data,
and even though i was an iterator from the container a, it now works as an iterator in b.
Here the situation is that (*i) == 0.
*/
b.clear(); // Now the iterator i is completely invalid.
int j = *i; // Undefined behavior!
/*
The data from b (which i pointed to) is gone.
This would be well-defined with STL containers (and (*i) == 5),
but with QVector this is likely to crash.
*/
//! [24]

View File

@ -533,10 +533,18 @@
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 must not take a copy of a container while
non-const iterators are active on that container. Java-style
iterators don't suffer from that limitation.
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 QVector, but
the problem exists for all the implicitly shared Qt containers.
\keyword foreach
\section1 The foreach Keyword

View File

@ -89,9 +89,12 @@
of data. Objects can easily be assigned, sent as function arguments,
and returned from functions.
Implicit sharing takes place behind the scenes; the programmer
does not need to worry about it. Even in multithreaded
applications, implicit sharing takes place, as explained in
Implicit sharing mostly takes place behind the scenes;
the programmer rarely needs to worry about it. However, Qt's
container iterators have different behavior than those from
the STL. Read \l{Implicit sharing iterator problem}.
In multithreaded applications, implicit sharing takes place, as explained in
\l{Thread-Support in Qt Modules#Threads and Implicitly Shared Classes}
{Threads and Implicitly Shared Classes}.
@ -105,9 +108,10 @@
greater than one. (This is often called \e {copy-on-write} or
\e {value semantics}.)
An implicitly shared class has total control of its internal data. In
An implicitly shared class has control of its internal data. In
any member functions that modify its data, it automatically detaches
before modifying the data.
before modifying the data. Notice, however, the special case with
container iterators; see \l{Implicit sharing iterator problem}.
The QPen class, which uses implicit sharing, detaches from the shared
data in all member functions that change the internal data.
@ -133,9 +137,9 @@
In this example, \c p1 and \c p2 share data until QPainter::begin()
is called for \c p2, because painting a pixmap will modify it.
\warning Do not copy an implicitly shared container (QMap,
QVector, etc.) while you are iterating over it using an non-const
\l{STL-style iterators}{STL-style iterator}.
\warning Be careful with copying an implicitly shared container
(QMap, QVector, etc.) while you use
\l{STL-style iterators}{STL-style iterator}. See \l{Implicit sharing iterator problem}.
\keyword implicitly shared classes
\annotatedlist shared

View File

@ -1594,6 +1594,11 @@ void QHashData::checkSanity()
need to keep iterators over a long period of time, we recommend
that you use QMap rather than QHash.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QHash::const_iterator, QMutableHashIterator
*/
@ -1791,6 +1796,11 @@ void QHashData::checkSanity()
internal data structure. If you need to keep iterators over a long
period of time, we recommend that you use QMap rather than QHash.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QHash::iterator, QHashIterator
*/

View File

@ -691,9 +691,12 @@ const QLinkedListData QLinkedListData::shared_null = {
Multiple iterators can be used on the same list. If you add items
to the list, existing iterators will remain valid. If you remove
items from the list, iterators that point to the removed items
will become dangling iterators. However, because of how \l{implicit
sharing} works, you must not take a copy of a container while
iterators are active on that container.
will become dangling iterators.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QLinkedList::const_iterator, QMutableLinkedListIterator
*/
@ -910,6 +913,11 @@ const QLinkedListData QLinkedListData::shared_null = {
items from the list, iterators that point to the removed items
will become dangling iterators.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QLinkedList::iterator, QLinkedListIterator
*/

View File

@ -1292,6 +1292,11 @@ void **QListData::erase(void **xi)
iterators over a long period of time, we recommend that you use
QLinkedList rather than QList.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QList::const_iterator, QMutableListIterator
*/
@ -1542,6 +1547,11 @@ void **QListData::erase(void **xi)
iterators over a long period of time, we recommend that you use
QLinkedList rather than QList.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QList::iterator, QListIterator
*/

View File

@ -1215,6 +1215,11 @@ void QMapDataBase::freeData(QMapDataBase *d)
items from the map, iterators that point to the removed items
will become dangling iterators.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QMap::const_iterator, QMutableMapIterator
*/
@ -1433,6 +1438,11 @@ void QMapDataBase::freeData(QMapDataBase *d)
items from the map, iterators that point to the removed items
will become dangling iterators.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QMap::iterator, QMapIterator
*/

View File

@ -643,8 +643,12 @@
\snippet code/doc_src_qset.cpp 10
Multiple iterators can be used on the same set. However, you may
not attempt to modify the container while iterating on it.
Multiple iterators can be used on the same set.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QSet::const_iterator, QMutableSetIterator
*/
@ -682,8 +686,10 @@
\snippet code/doc_src_qset.cpp 12
Multiple iterators can be used on the same set. However, you may
not attempt to modify the container while iterating on it.
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QSet::iterator, QSetIterator
*/

View File

@ -957,6 +957,11 @@
iterators}. The STL-style non-const iterator is simply a typedef
for "T *" (pointer to T).
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QVector::begin(), QVector::end(), QVector::const_iterator, QMutableVectorIterator
*/
@ -969,6 +974,11 @@
iterators}. The STL-style const iterator is simply a typedef for
"const T *" (pointer to const T).
\warning Iterators on implicitly shared containers do not work
exactly like STL-iterators. You should avoid copying a container
while iterators are active on that container. For more information,
read \l{Implicit sharing iterator problem}.
\sa QVector::constBegin(), QVector::constEnd(), QVector::iterator, QVectorIterator
*/