The Dangers of Copy On Write (COW)
-
I had the following function in my code:
@ResultConstIterator getIterator(const ResultVector& checkArray, size_t argumentNumber)
{
if (argumentNumber < checkArray.size()) {
return checkArray.begin()+argumentNumber;
} else {
return checkArray.end();
}
}
@which was called like this:
@
ResultConstIterator entry = getIterator(checkArray, nr);
if (entry != checkArray.end()) {
doSomething(entry);
}
@When I changed the type of ResultVector from std::vector to QVector suddenly doSomething was called in every case. Fortunately I had a unit test that caught this. After some debugging and head scratching I found the cause of the changed behaviour.
Do you also see it?
-
I am bit curious here.
QVector::end () returns a pointer pointing to the imaginary item after the last item in the vector.
And The vector::end returns iterator [Random Access Iterator] referring the last element .
'entry' is of type ResultConstIterator .So when checkArray is QVector, @if (entry != checkArray.end()) @ means you are comparing a ResultConstIterator with an iterator?
Just to make sure, if i am understanding correctly.
And yea, Implicit sharing is the main difference between a std::vector and QVector.
-
The problem is indeed comparing an iterator with a const iterator, which is not easy to prevent in C++03. The correct code should be:
@
ResultConstIterator entry = getIterator(checkArray, nr);
ResultConstIterator constEnd = checkArray.end();
if (entry != constEnd) {
doSomething(entry);
}
@QVector::end() does a detach() resulting in different end pointers.
With QVector constEnd() can be used, and C++11 has cend().