Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;最后一个元素损坏迭代器_C++_Vector_Iterator - Fatal编程技术网

C++ C++;最后一个元素损坏迭代器

C++ C++;最后一个元素损坏迭代器,c++,vector,iterator,C++,Vector,Iterator,我当前在vector.erase()方面有问题 现在,第一个被破坏的对象成功地从向量中移除,然后我得到一个错误,迭代器不可解引用,指向第73行(?)的向量库 然后我使用msvc调试器进行检查。在数据预览中,它显示迭代器指向gameObjects的最后/最新元素。然后将其删除(擦除(它)),之后数据预览不会更改,并调用它->getDestroyed()将导致错误消息 调试断言失败!向量迭代器不可解引用 PS:我检查了cplusplus.com,vector.erase应该返回一个新的有效迭代器,所

我当前在vector.erase()方面有问题

现在,第一个被破坏的对象成功地从向量中移除,然后我得到一个错误,迭代器不可解引用,指向第73行(?)的向量库

然后我使用msvc调试器进行检查。在数据预览中,它显示迭代器指向gameObjects的最后/最新元素。然后将其删除(擦除(它)),之后数据预览不会更改,并调用它->getDestroyed()将导致错误消息

调试断言失败!向量迭代器不可解引用

PS:我检查了cplusplus.com,vector.erase应该返回一个新的有效迭代器,所以我不确定我把它弄糟了

欧元:在我被告知“擦除-删除”习惯用法后,我继续往下说,最后得出了以下无法编译的结论。由于我的功能是gameObject的成员,我不确定如何成功调用remove_if。谢谢

gameObjects.erase(remove_if(gameObjects.begin(), gameObjects.end(), gameObject::getDestroyed), gameObjects.end());
欧元2:很多人指出第一个对象没有被检查。我很可能应该指出这一点,但第一个要素始终是球员,不应该被删除。谢谢你的评论。我将尝试一个简单的前向循环,但不要太花哨

欧元3:我尝试了Jonathan Mees建议的代码,但得到了完全相同的错误消息。我会尝试找出它到底发生在哪里,但我不能再在擦除部分设置断点了。会有点乱


欧元4:通过删除else{}条件并始终递减迭代器,问题得以解决。再次感谢您的回复。

假设向量中有两个对象,最后一个对象标记为已销毁。当您调用
erase
时,它将返回一个新的、有效的迭代器,该迭代器指向已删除元素之后的元素。删除的元素之后没有元素,因此返回的迭代器是
gameObjects.end()
。然后继续循环的顶部并取消引用该迭代器,该迭代器无效。如果希望迭代器指向有效元素,则需要在擦除之后减小迭代器

另一个注意事项是:如果您曾经希望删除第一个元素,它将不会被删除。当迭代器
==gameObjects.begin()
时,循环将退出,因此不会检查第一个元素


你有什么理由想反过来做吗?如果没有具体原因,我建议您使用@Borgleader推荐的方法。

您的循环有点混乱-您正在向后迭代,忽略第一个元素,并多次测试某些元素。我可以推荐rbegin()作为替代方案吗?

返回:

最后删除的元素后面的迭代器。如果迭代器pos引用最后一个元素,则返回
end()
迭代器

这意味着
vector::erase
永远不会返回
vector::begin
(除非您删除了容器中的唯一元素)。因此
在调用
vector::erase
后,它将始终被再次取消引用。即使调用
vector::erase
返回了
vector::end
,它也将被取消引用,这当然是非法的

代替这个循环,考虑使用为此目的而设计的:

gameObjects.erase(remove_if(begin(gameObjects),
                            end(gameObjects),
                            [](const auto& i){ return i.getDestroyed(); }), end(gameObjects));
编辑:

我注意到你试着在编辑中使用这个。不能将裸函数指针用作谓词。如果你想避免lambda,你应该考虑使用:

如果阅读该行有困难,请随意使用任意多的变量:

auto p = mem_fn(&gameObject::getDestroyed);
auto result = remove_if(begin(gameObjects), end(gameObjects), p);

gameObjects.erase(result, end(gameObjects));

好的,谢谢你的帮助。我继续读下去。因为我的检查方法是一个成员,所以我不确定如何构建erase_if调用。第一个对象始终是玩家,他不应该被删除。作为对@Borgleader的回应,我尝试构建一个类似于我发现的wikipedia页面的页面,但由于它是gameObject的一个成员,因此很难使用该方法调用。@Jonathan Mee给出了一个如何使用C++11 lambdas实现的示例。我只是删除了else{}条件,并始终减少迭代器。工作起来很有魅力,我很高兴:)。再次感谢您抽出时间。我发现你的解释很容易理解,所以也感谢你对我的教育^^。有人告诉我,向后迭代效率更高。第一个要素始终是玩家自己。我将尝试与rbegin()混在一起,如果这能改善情况,我将尝试:)。谢谢。你的代码完全不可读。在我的团队中无法通过审核。我尝试了你的代码,做了一个小小的更改I->getDestroyed(),但得到了相同的错误消息。我会检查相同的问题是否仍然存在,或者是否有其他问题。PS:不知何故,我无法删除或编辑第一条评论:/。@celphy你似乎在试图避开lambda。我已经使用
mem\u fn
进行了更新,以避免lambda。在看了他们两个之后,我同意我觉得这更吸引人。我还提供了一个演示代码工作的实例,希望能帮助您修改函数。@LightnessRacesinOrbit以前说过我在一行中塞得太多;)我把它拆开,希望能满足你们团队的可读性标准。我可能会这样格式化它:这样可以正确地阅读。似乎是为了证明我的观点,你的版本中缺少了一个
(我把它放在我的版本中,这样你就可以看到它在哪里了)。
gameObjects.erase(remove_if(begin(gameObjects),
                            end(gameObjects),
                            [](const auto& i){ return i.getDestroyed(); }), end(gameObjects));
gameObjects.erase(remove_if(begin(gameObjects),
                            end(gameObjects),
                            mem_fn(&gameObject::getDestroyed)), end(gameObjects));
auto p = mem_fn(&gameObject::getDestroyed);
auto result = remove_if(begin(gameObjects), end(gameObjects), p);

gameObjects.erase(result, end(gameObjects));