очень странное поведение обратного итератора в C ++ - PullRequest
0 голосов
/ 11 октября 2018

Это тест, который я провел сегодня на своем компьютере, меня попросили реализовать класс Гарднера с двумя функциями - каждая пометит участок земли, на котором стоит Гарднер, как косил и переместит Гарднера на 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 Ответ

0 голосов
/ 11 октября 2018

Чтобы понять, что происходит с вашим обратным итератором, взгляните на 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 или сохранить его во временной переменной и проверить это в отладчике.

...