【问题标题】:Why does calling a function on an iterator that points to an object not let me change the object itself? [duplicate]为什么在指向对象的迭代器上调用函数不允许我更改对象本身? [复制]
【发布时间】:2020-05-10 22:46:32
【问题描述】:

我有一个包含 Enemy 对象的向量,称为 enemiesOnField。当调用一个可能会改变单个敌人坐标的函数 takeYourTurn 时,我注意到即使改变发生在函数内,它也不会持续存在于 enemiesOnField 向量中。这使我相信,当通过迭代器调用此函数时,它以某种方式在副本上调用,而不是在原始对象上调用。当通过 [] 运算符返回的引用调用时,一切正常。

没有按预期工作的代码被注释掉:

void World::letNPCsAct()
{

    /* this doesn't work
    for (auto it : enemiesOnField)      
        it.takeYourTurn();*/

    // this works
    for (int i = 0; i < enemiesOnField.size(); ++i)
        enemiesOnField[i].takeYourTurn();

}

为什么会这样??

【问题讨论】:

  • 基于范围的循环会修改原始对象的 副本。您需要循环引用来修改原始向量。
  • 类似于:for (const auto& it :enemyOnField) it.takeYourTurn();行得通吗?

标签: c++


【解决方案1】:

正常的 for 循环有效,因为您直接更改内容。默认情况下,基于范围的 for 循环会创建副本。所以你的内容不会被修改。如果你想修改,你需要使用下面的参考。

for (auto& it: enemiesOnField) {    
    it.takeYourTurn();
}

【讨论】:

    【解决方案2】:

    range-for 循环为您提供范围中包含的 对象,而不是它们的迭代器。

    for (auto it : enemiesOnField)      
        it.takeYourTurn();
    

    这不是通过迭代器调用takeYourTurn。它在enemiesOnField 中包含的对象的副本上调用它。

    如果你想让它使用引用,你必须声明它这样做:

    for (auto& enemy : enemiesOnField)      
        enemy.takeYourTurn();
    

    您使用的 range-for 在语义上等同于以下内容:

    {
        auto&& __range = enemiesOnField;
        auto __begin = __range.begin();
        auto __end = __range.end();
        for (; __begin != __end; ++__begin)
        {
            auto it = *__begin;
            it.takeYourTurn();
        }
    }
    

    (注意__range、__begin、__end这些名称仅供说明,用户代码不能引用这些对象)

    请注意,auto it = *__begin 制作了__begin 引用的对象的副本。

    【讨论】:

      【解决方案3】:

      试试这个:

      for (auto& it: enemiesOnField) {    
          it.takeYourTurn();
      }
      

      您需要遍历引用。

      【讨论】:

        猜你喜欢
        • 2012-06-28
        • 2021-03-30
        • 1970-01-01
        • 2014-03-15
        • 2018-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多