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.
So, if the call to QVector::begin()
happens first, then the container's underlying storage is reallocated, and the subsequent call to QVector::cbegin()
will return the same pointer. However, reverse them and the call to QVector::cbegin()
returns a pointer to the shared storage before any reallocation happens.