Очень странное поведение обратного итератора в C++

Это из теста, который я сегодня провел на своем компьютере, меня попросили реализовать класс Гарднера с двумя функциями - каждая из них пометит участок земли, на котором стоит Гарднер, как скашенный, и переместит Гарднера на 3 единицы влево или вправо, Если на пути Гарднера есть какой-либо участок земли, помеченный как скошенный, он пропустит его и перейдет к следующему.

Я смоделировал землю, используя вектор логических переменных. Я использовал std::find() с прямым итератором, чтобы найти землю, которая не косится в правильном направлении, и я использовал обратный итератор в левом направлении. Прямой итератор работает как положено. Однако обратный итератор дал странные результаты. Если быть более точным, например, в отладчике Visual Studio, он показал значение, на которое указывает обратный итератор, значение false(что и ожидалось), но когда я разыменовал обратный итератор, я получил значение true. Это может быть воспроизведено в следующем коде, я приложил код, любая помощь приветствуется.

#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

1 ответ

Решение

Чтобы понять, что происходит с вашим обратным итератором, посмотрите на reverse_iterator в cppreference. Более конкретно, посмотрите на метод base():

Базовый итератор ссылается на следующий элемент (из std::reverse_iterator::iterator_type в перспективе) к элементу reverse_iterator в настоящее время указывает на. То есть &*(rit.base() - 1) == &*rit,

По-английски:

*rit.base() (обратного итератора) будет обращаться к элементу mLands, который является одним до того, что *rit иметь доступ. Этот сдвиг между *rit а также *rit.base() позволяет сделать mLands.rend() логически указывает на первый элемент mLands, Это зеркальный эквивалент mLands.end() указывая на последний элемент mLands,

Теперь о том, что вы видите в отладчике. Скорее всего, ваш отладчик показывает вам значение rit.base() который указывает на один элемент ранее mLands, тогда что rit указывает логически. Это может объяснить несоответствие, которое вы видите здесь. Для отладки, если вы не уверены, что показывает отладчик, самое безопасное - напечатать значение *rit или сохранить его во временной переменной и проверить это в отладчике.

Другие вопросы по тегам