简体   繁体   中英

very weird behaviour of reverse iterator in C++

This is from a test I took today on my computer, I was asked to implement a Gardner class with two functions - each one will mark the piece of land the Gardner stands on as mowed and move the Gardner by 3 units to the left or right. If there is any piece of land marked as mowed on Gardner's path, he will skip it and move on to the next one.

I modelled the land using a vector of boolean variables. I was using std::find() with the forward iterator to find the land which is not mowed in the right direction, and I was using the reverse iterator in the left direction. The forward iterator works as expected. However, the reverse iterator produced some weird results. To be more specific, for example, in the debugger of Visual Studio, it showed the value the reverse iterator points to is false(which was expected), but when I dereference the reverse iterator, I got true. This can be reproduced in the following code, I have attached the code, any help is appreciated.

#include <iostream>
#include <vector>
#include <algorithm>

class Gardener
{
public:
    Gardener(int n, int position)
        : mLands(n, false)
        , mPosition(position - 1)
    {
    }

    /**
    *   \brief Gardener has mowed the lawn at current house and moved left.
    *
    **/
    void mowAndMoveLeft()
    {
        mLands[mPosition] = true;
        //auto it = std::find(mHouses.rbegin() + mHouses.size() - mPosition + 1, mHouses.rend(), false);
        //it = std::find(it + 1, mHouses.rend(), false);
        //it = std::find(it + 1, mHouses.rend(), false);
        auto it = mLands.rbegin() + mLands.size() - mPosition + 1;
        int counter = 3;
        while (--counter >= 0)
        {
            while (it != mLands.rend())
            {
                if (*it == false)
                {
                    ++it;
                    break;
                }

                ++it;
            }
        }

        mPosition = mLands.rend() - it;
    }

    /**
    *   \brief Gardener has mowed the lawn at current house and moved right.
    *
    **/
    void mowAndMoveRight()
    {
        mLands[mPosition] = true;
        auto it = std::find(mLands.begin() + mPosition + 1, mLands.end(), false);
        it = std::find(it + 1, mLands.end(), false);
        it = std::find(it + 1, mLands.end(), false);
        mPosition = it - mLands.begin();
    }

    /**
    *   \return house number that gardener is mowing right now.
    *
    **/
    int whereAmI()
    {
        return mPosition + 1;
    }

private:
    std::vector<bool> mLands;
    std::size_t mPosition;
};

#ifndef RunTests
int main(int argc, const char* argv[])
{
    Gardener g(10, 2);
    std::cout << g.whereAmI() << '\n';

    g.mowAndMoveRight();
    std::cout << g.whereAmI() << '\n';

    g.mowAndMoveRight();
    std::cout << g.whereAmI() << '\n';

    g.mowAndMoveLeft();
    std::cout << g.whereAmI() << '\n';
}
#endif

To understand what is going on with your reverse iterator, have a look at reverse_iterator at cppreference . More specifically, look at the base() method :

The base iterator refers to the element that is next (from the std::reverse_iterator::iterator_type perspective) to the element the reverse_iterator is currently pointing to. That is &*(rit.base() - 1) == &*rit .

In English:

*rit.base() (of a reverse iterator) would access an element of mLands which is one before what *rit hast to access. This shift between *rit and *rit.base() makes it possible to make mLands.rend() logically points past the first element of mLands . It is the mirror equivalent of mLands.end() pointing past the last element of mLands .

Now, for what you see in the debugger. Most likely, your debugger is showing you the value of rit.base() which points to one element earlier in mLands , than what rit is pointing logically. This can explain the discrepancy you are seeing here. For debugging, if you are uncertain what the debugger is showing, the safest thing here is to print the value of *rit or to store it in a temporary variable, and check that in the debugger.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM