Could anyone explain me, why the following code produces different results depending on copying QStringList:
#include <stdio.h>
#include <QStringList>
bool qtTest(bool b)
{
QStringList list;
list.push_back("0");
list.push_back("1");
list.push_back("2");
QStringList::const_iterator it = list.end();
if (b) {
// 'static' to prevent optimization
static QStringList copy = list;
}
--it; // 2
--it; // 1
--it; // 0
++it; // 1
++it; // 2
--it; // 1
++it; // 2
++it; // end
return it == list.end();
}
int main(int, char *[])
{
printf("equality with copy: %d", qtTest(true));
printf("equality without copy: %d", qtTest(false));
return 0;
}
Output:
equality with copy: 0
equality without copy: 1
However, std::vector provides equal output regardless of copying.
Debian 7 x86 GCC x86 32 bit Qt 5.1.0 debug qmake spec linux-g++
Thanks for answers
That happens because QStringList is one of Qt's implicit shared classes, that means that when you do the copy you're actually only copying a reference to the list contents (the "real" copying happens only when/if one of the objects is being modified).
If you want to iterate like you're doing here, you should change the end() method with constEnd(), just like this:
QStringList::const_iterator it = list.constEnd();
if (b) {
// 'static' to prevent optimization
static QStringList copy = list;
}
--it; // 2
--it; // 1
--it; // 0
++it; // 1
++it; // 2
--it; // 1
++it; // 2
++it; // end
return it == list.constEnd();
While end() method returns an iterator, constEnd() (or cend()) returns a const_iterator, so that's what you need to use in this case. There's an interesting article if you want to investigate deeper:
http://doc.qt.digia.com/qq/qq12-qt4-iterators.html#implicitsharinganditerators
I hope that this can help you.
QStringList::const_iterator it = list.end();
Be very careful about this call -- it will cause a (maybe unwanted) detach. Use constEnd() if you don't want it. And preventing a further question, let me quote the docs:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With