C++ 中反向迭代器的非常奇怪的行为

瑞安

这是我今天在我的计算机上进行的一项测试,我被要求实现一个具有两个功能的 Gardner 类 - 每个功能都会将 Gardner 所在的一块土地标记为已割草,并将 Gardner 向左或向右移动 3 个单位. 如果 Gardner 的路径上有任何标记为已修剪的土地,他将跳过它并移至下一块。

我使用布尔变量向量对土地进行建模。我使用 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
迈克尔·维克斯勒

要了解反向迭代器发生了什么,请查看 cppreference中的reverse_iterator更具体地说,看看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()which的值更早地指向 中的一个元素mLands,而不是rit逻辑上指向的值。这可以解释您在此处看到的差异。对于调试,如果您不确定调试器显示的是什么,这里最安全的做法是打印 的值*rit或将其存储在临时变量中,然后在调试器中检查。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章