我有以下代码:
static std::map<int,int> myFunction(std::list<int>& symbols){
std::map<int,int> currCounts;
std::map<int,int> payHits;
for (std::list<int>::iterator l_itr = symbols.begin(); l_itr != symbols.end(); ++l_itr){
myFunction_helper(*l_itr, l_itr, symbols, currCounts, payHits, 0);
}
return payHits;
}
static inline void myFunction_helper(int next, std::list<int>::iterator& pos, std::list<int> remainingSymbols, std::map<int,int> currCounts, std::map<int,int>& payHits, int i){
currCounts[next] = currCounts.count(next) > 0 ? currCounts[next] + 1 : 1;
remainingSymbols.erase(pos);
if (i < numTiles && remainingSymbols.size() > 0){
if (currCounts[next] == hitsNeeded[next]){
int pay = symbolPays[next];
payHits[pay] = payHits.count(pay) > 0 ? payHits[next] + 1 : 1;
}
else{
for (std::list<int>::iterator l_itr = remainingSymbols.begin(); l_itr != remainingSymbols.end(); ++l_itr){
myFunction_helper(*l_itr, l_itr, remainingSymbols, currCounts, payHits, i+1);
}
}
}
else{
payHits[0] = payHits.count(0) > 0 ? payHits[0] + 1 : 1;
}
}
它应该采用一组值并给出一些要求(numTiles (int)、hitsNeeded(符号图和需要选择它们才能获胜的次数))。我的代码基于 visual studio(最新版本)构建,但是当我尝试执行它时,第一次调用 myFunction_helper 时出现错误“列表删除迭代器超出范围”。我该如何避免这种情况?我特意按值传递了 remainingSymbols,这样我就可以在不影响其他递归堆栈框架成员的情况下修改它。我该如何解决这个问题,为什么会引发异常?
解决方案
从参数中删除迭代器。然后在迭代时使用以下代码片段:
int next = *l_itr;
l_itr = symbols.erase(l_itr);
myFunction_helper(next, remainingSymbols, currCounts, payHits, i+1);
symbols.push_front(next);
对于外部函数也是如此。将元素推到最前面不会破坏列表的迭代并允许我想要的东西(推到最前面在列表上也非常便宜)。
最佳答案
同意下面的评论。这是一个糟糕的答案,因为我们对业务案例的了解还不够多,无法提出一个好的解决方案。我在这里留下一个编辑过的版本,因为我刚刚恢复了被破坏的问题,它确实解释了尝试失败的原因。
为什么会引发异常
std::list<int> remainingSymbols
是按值传递的,所以pos
不再相关。引用来源list
,而不是 remainingSymbols
中源列表的拷贝.对一个 list
使用迭代器在另一个,即使是拷贝,也是致命的。
解决方案
常见的解决办法是解决办法是通过remainingSymbols
通过引用:std::list<int> & remainingSymbols
,但由于这会中断回溯,因此您不能这样做。
相反,您必须为该位置传递一个不同的标识符,也许是索引。不幸的是,交互和重新迭代 list
这是一项昂贵的任务,几乎总是超过 list
的快速插入和删除的好处。 .
关于c++ - 列出超出范围的删除迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51052150/