The behavior you're observing has to do with the order of the calls being made to QVector::begin and QVector::cbegin . If the call to the former happens before the call to the latter, then their return values compare equal, but if you reverse the order, they do not compare equal. This can be demonstrated by the following code:

QVector<int> c; std::cout << static_cast<void const *>(c.begin()) << std::endl; std::cout << static_cast<void const *>(c.cbegin()) << std::endl;

The addresses printed will be the same. However, if you swap the order of the two print statements, the addresses will be different.

If you dig into the source code for the two member functions, you'll see

inline iterator begin() { detach(); return d->begin(); } inline const_iterator cbegin() const { return d->constBegin(); }

And tracing back further, the bodies of both d->begin() and d->constBegin() are identical. So the difference is in the call to QVector::detach() in the first case. This is defined as

template <typename T> void QVector<T>::detach() { if (!isDetached()) { #if QT_SUPPORTS(UNSHARABLE_CONTAINERS) if (!d->alloc) d = Data::unsharableEmpty(); else #endif reallocData(d->size, int(d->alloc)); } Q_ASSERT(isDetached()); }

An explanation of what's going on can be found here.

Qt’s containers are implicitly shared – when you copy an object, only a pointer to the data is copied. When the object is modified, it first creates a deep copy of the data so that it does not affect the other objects. The process of creating a deep copy of the day is called detach



Since, STL-style iterators are conceptually just pointers, they make modification to the underlying data directly. As a consequence, non-const iterators detach when created using Container::begin() so that other implicitly shared instances do not get affected by the changes.