Weird behavior when using QVectorIterator::previous()
-
I have a very simple program in which I iterate over a QVector of structs. Iterating forward works as expected, when iterating backwards I have random values in my struct.
@struct X
{
public:
X() : A(0) , B(0), C(0), D(0) { }X(int a, int b, int c, int d) : A(a), B(b), C(c), D(d) {}
/// Copy constructor
//X(const X& x) : A(x.A), B(x.B), C(x.C), D(x.D) { }int A; int B; int C; int D;
};int main(int argc, char* argv[]) {
// Initialize
QVector<X> _vector;
for (int i = 0; i < 5; i++)
{
X _x(i+0, i+1, i+2, i+3);std::cout << _x.A << "; " << _x.B << "; " << _x.C << "; " << _x.D << std::endl; _vector.push_back(_x);
}
std::cout << "------------" << std::endl;
// Forward iteration
{
QVectorIterator<X> _iter(_vector);
while (_iter.hasNext())
{
const X _x = _iter.next();
std::cout << _x.A << "; " << _x.B << "; " << _x.C << "; " << _x.D << std::endl;
}
}std::cout << "------------" << std::endl;
/// backward iteration
{
QVectorIterator<X> _iter(_vector);
_iter.toBack();
while (_iter.hasPrevious())
{
const X _x = _iter.previous(); // _x contains invalid values
//const X& _x = _iter.previous(); // _x contains expected values
std::cout << _x.A << "; " << _x.B << "; " << _x.C << "; " << _x.D << std::endl;
}
}return 0;
}@Output:
0; 1; 2; 3
1; 2; 3; 4
2; 3; 4; 5
3; 4; 5; 6
4; 5; 6; 70; 1; 2; 3
1; 2; 3; 4
2; 3; 4; 5
3; 4; 5; 6
4; 5; 6; 72; 6; 5; 1
2; 6; 5; 1
2; 6; 5; 1
2; 6; 5; 1
2; 6; 5; 1I made the following observations:
- It only happens on "const X _x = _iter.previous()" (Line 45). In my understanding this should call the default copy constructor
- When using "const X& _x = _iter.previous()" (Line 46) the problem doesn't happen, so QVectorIterator::previous() seems to do the right thing
- When explicitely defining a copy constructor (Line 9) the problem doesn't happen
- When using any other form of iteration (using indices, STL Style iterators) the problem doesn't happen.
- It only happens in Release mode (VisualStudio 2010)
- Tested using Qt 4.8.4
To me this looks like a compiler optimization gone wrong. Am I missing anything here?
-
The documentation indicates that next(), previous(), peekNext(), and peekPrevious() return a T&. So the weird part is that the forward iteration works, the backward iteration is behaving as expected.
-
I know that they return a T&, but I don't understand why this shouldn't work. Shouldn't
@const X _x = _iter.previous()@just call the default copy constructor provided by the compiler? Shouldn't this be equivalent to explicitely declaring a copy constructor which does a member-wise copy? (As stated in "This article":http://www.cplusplus.com/articles/y8hv0pDG/ ). With the explicit copy constructor it works.