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; 7

    0; 1; 2; 3
    1; 2; 3; 4
    2; 3; 4; 5
    3; 4; 5; 6
    4; 5; 6; 7

    2; 6; 5; 1
    2; 6; 5; 1
    2; 6; 5; 1
    2; 6; 5; 1
    2; 6; 5; 1

    I 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.