我有以下代码:
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时出现错误“列表擦除迭代器超出范围”。如何避免这种情况?我故意按值传递了剩余符号,以便可以修改它而不影响其他递归堆栈框架成员。我该如何解决?为什么会引发异常?
从参数中删除迭代器。然后,当您迭代时,请使用以下代码段:
int next = *l_itr;
l_itr = symbols.erase(l_itr);
myFunction_helper(next, remainingSymbols, currCounts, payHits, i+1);
symbols.push_front(next);
类似地,外部函数也是如此。将元素推到最前面不会破坏列表的迭代,并且允许我想要的东西(推到最前面也很便宜)。
答案 0 :(得分:3)
同意以下评论。这是个废话,因为我们对业务案例了解不足,无法提出好的解决方案。我将其保留在编辑后的版本中,因为我刚刚回复了故意破坏的问题,它确实说明了尝试失败的原因。
std::list<int> remainingSymbols
是按值传递的,因此pos
不再相关。它引用源list
,而不是remainingSymbols
中源列表的副本。对于另一个list
,甚至一个副本,使用迭代器是致命的。
常见的解决方案是通过引用remainingSymbols
传递std::list<int> & remainingSymbols
,但是由于这会破坏回溯,所以您不能这样做。
相反,您将必须为该位置(可能是索引)传递一个不同的标识符。不幸的是,插入和重新迭代list
是一项昂贵的任务,几乎总是胜过list
的快速插入和删除操作。
答案 1 :(得分:1)
您不能将一个容器中的迭代器与另一个容器中的迭代器一起使用,而可以使用offset,但是对于std::list
来说,这是非常无效的。另外,将std::list
与int
一起使用通常不是一个好主意-您的数据很小,并且很可能与数据本身以及缓存未命中相比,用于维护列表项的内存至少多两倍。您最好使用std::vector<int>
并传递偏移量,而不是迭代器。另外,您可以使用vector<>
使用移动擦除习惯用法,但是即使删除向量中间的int
也是相对便宜的,最有可能比跳过std::list
个节点的开销便宜。