【问题标题】:Issue erasing an element from a list in c++从 C++ 中的列表中删除元素的问题
【发布时间】:2017-11-05 15:24:32
【问题描述】:

我有以下代码:

list<Item> playerItems = player.GetPlayerItems();

        list<Item>::iterator iterator;
        for (iterator = playerItems.begin(); iterator != playerItems.end(); ++iterator)
        {
            if (itemToSell == (*iterator).GetName())
            {
                if ((*iterator).GetCost() < GetShopGold())
                {
                    SetShopItem(*iterator);
                    SetShopGold(GetShopGold() - (*iterator).GetCost());

                    player.SetPlayerGold(player.GetPlayerGold() + (*iterator).GetCost());

                    //The issue is here
                    iterator = player.GetPlayerItems().erase(iterator);
                    return true;
                }
                else
                {
                    cout << "I can't afford that..." << endl;
                }
            }
        }

这是 RemovePlayerItem 代码:​​

void Player::RemovePlayerItem(list<Item>::iterator& iterator)
{
    iterator = _playerItems.erase(iterator);
}

当我运行代码时,我收到以下错误:

_DEBUG_ERROR("list erase iterator outside range");

我google了一下,似乎和我的迭代器有关,但我不确定错误和迭代器之间的关系。

相比之下,如果我将 _playerItems 变量设为全局变量,然后使用此全局变量启动/结束迭代器,则如果我使用以下代码 iterator = player._playerItems.erase(iterator);,代码运行良好

编辑

这是 GetPlayerItems() 函数

list<Item> Player::GetPlayerItems()
{
    return _playerItems;
} 

谁能指出我正确的方向?

【问题讨论】:

  • 不要到处写(*iterator).foo,你可以写iterator-&gt;foo
  • GetPlayerItems() 是按引用返回还是按值返回?
  • iteratorplayerItem 的迭代器,而不是player.GetPlayerItems() 的返回值。您正在尝试使用指向不同列表的迭代器从一个列表中擦除。
  • @IgorTandetnik - 这不是评论,而是答案。

标签: c++ iterator erase


【解决方案1】:

iteratorplayerItems 的迭代器。目前尚不清楚player.GetPlayerItems() 返回什么(因为您忽略了显示它的定义甚至是声明),但无论它是什么,playerItems 都是一个单独的、不同的列表——GetPlayerItems() 返回的内容的副本。

然后,您尝试使用指向另一个列表的迭代器从一个列表中擦除。这表现出未定义的行为 - someList.erase(iter) 期望 iter 成为 someList 的有效迭代器。

【讨论】:

  • 好吧,这是有道理的,我已经更新了代码以包含 GetPlayerItems 函数。所以我假设的是,我需要引用原始列表,而不是复制。我会再玩一些,谢谢你的洞察力
  • 所以GetPlayerItems() 返回_playerItems 的副本(然后playerItems 本身就是该副本的副本)。即使您设法从该副本中正确擦除,它也不会影响_playerItems 成员变量。
【解决方案2】:

在这里,您尝试使用指向另一个列表的迭代器从一个列表中擦除。

为什么不能使用 iterator = playerItems.erase(iterator);而不是 iterator = player.GetPlayerItems().erase(iterator);在循环内。

为什么您尝试使用 get 函数调用 (player.GetPlayerItems()) 访问同一个列表,因为您已经有对同一个列表的引用。

【讨论】:

    猜你喜欢
    • 2011-04-02
    • 2021-12-30
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 2023-03-27
    • 2012-03-30
    相关资源
    最近更新 更多