debug断言矢量迭代器不可用find_if删除

debug assert vector iterator not dereferncable with find_if

本文关键字:find if 删除 断言 迭代器 debug      更新时间:2023-10-16

我想将我的循环转换为find_if lambda,但我总是会得到相同的结果向量迭代器,而不是删除。

void SearchObjectDescription(std::vector<std::string>& input, Player & player)
{
    //--local variable
    bool found = false;
    //std::find_if
    std::vector<std::string>::iterator i = std::find_if(input.begin(), input.end(),[&](Player player)
    {
        if ((player.InInventory((*i)) ) == true)
        {
            std::cout << (player.GetInventory().ItemByName((*i))).ExamineObject() << std::endl;
            return true;
        }
        else
        {
            std::cout << "Object not in invetory!" << std::endl;
            return false;
        }
    });
    //original for loop
    //for (std::vector<std::string>::iterator i = input.begin()+1; i != input.end(); i++)
    //{
    //  if (player.InInventory((*i))== true)
    //  {
    //      std::cout << (player.GetInventory().ItemByName((*i))).ExamineObject() << std::endl;
    //      found = true;
    //      break;
    //  }
    //}
    //if (found ==false)
    //{
    //  std::cout << "Object not in invetory!" << std::endl;
    //}
}

有人可以帮我吗?

您错误地考虑了lambda。 std::find_if函数是第三个参数,即获取向量元素的lambda,如果是您搜索的元素,则返回。

lambda的目的是拿一个元素,并确定它是否合适。

然而,您的lambda不会收到字符串向量的元素,而是将播放器作为参数。但是您显然没有玩家列表,您有字符串列表。为什么要检查的元素应该是Player

而是捕获播放器变量并接收要检查的元素。看起来像这样:

void SearchObjectDescription(std::vector<std::string>& input, Player & player)
{
    auto i = std::find_if(input.begin(), input.end(),[&](const std::string& item)
    {
        // item is equal to the current element being checked
        // player is captured by reference because of [&]
        // if the item `item` is in inventory, return true.
        return player.InInventory(item);
    });
    if (i != input.end()) {
        // if it's not equal to the end, *i is the found item.
    }
}

请注意,在C 14中,您可以在lambda中接收auto&&,并将其推荐为string&

std::find_if(input.begin(), input.end(), [&](auto&& item)
{ 
     // type of item is std::string&
     // ...
});

您不能在lambda内部使用i迭代器,因为直到std::find_if()退出后才初始化它。您需要使用lambda的输入参数,该参数将是vectorstd::string,而不是Player对象。

另外,您没有检查std::find_if()的返回值,以确保在取消给它之前具有有效的迭代器。

您没有正确地将for循环转换为基于lambda的std::find_if()。改用此方法:

void SearchObjectDescription(std::vector<std::string>& input, Player & player)
{
    auto i = std::find_if(input.begin()+1, input.end(),
        [&](const std::string &s) { return player.InInventory(s); });
    if (i != input.end())
    {
        std::cout << (player.GetInventory().ItemByName(*i)).ExamineObject() << std::endl;
    }
    else
    {
        std::cout << "Object not in inventory!" << std::endl;
    }
}