我有一个代码:
it = tableAndHand.begin();
while(++it != tableAndHand.end()) {
if(*it == *(--it)) {
++cardCount;
++it;
} else {
cardCounts1.insert(pair<int,int>(cardCount,*it));
while(cardCount > 1) {
it = tableAndHand.erase(--it);
--cardCount;
}
++it;
}
}
cardCounts1.insert(pair<int,int>(cardCount,*(--it)));
while(cardCount > 1) {
it = tableAndHand.erase(--it);
--cardCount;
}
tableAndHand是一个开始时7个值的列表,在删除一些值后,我在那个有问题的地方得到了分段错误,为什么会这样?
列表中的值被排序,并且它在列表{0,0,0,1,1,2,2}上失败,在某处迭代1s(在正确擦除2 0之后,因此列表的大小已经是5)。
我只是想将唯一值的计数保存到map card1中,并从列表中删除重复的值,我的算法出了什么问题?
编辑:看起来问题是(* it == *( - it))没有从左到右评估,虽然我在cplusplus.com上关于运营商的文章中找不到“==”的评价在其他一些网站上,他们说它是从左到右进行评估的。关于它的一些很好的联系?EDIT2:好的,它有效,我忘了将tableAndHand.erase( - it)迭代器分配给它,现在它完美而快速地工作:)
答案 0 :(得分:3)
在循环中将it
最多增加三次,然后再与结束进行比较。
擦除而不保存新的迭代器。
很多副作用。
if(*it == *(--it)) {
的排序尚未定义,因此您最终可能会将元素与自身进行比较。 (==
不是序列点,因此可以按任意顺序评估*it
和*(--it)
。
您没有检查tableAndHand
是否为空 - 您在检查之前会增加it
。
答案 1 :(得分:1)
在循环的每次迭代中增加it
两次:
while(++it != tableAndHand.end()) { // <---- IN THIS LINE
//HERE IS THE PROBLEM
if(*it == *(--it)) {
++cardCount;
++it; // <----- AND EITHER HERE
} else {
cardCounts1.insert(pair<int,int>(cardCount,*it));
while(cardCount > 1) {
tableAndHand.erase(--it);
--cardCount;
}
++it; // <----- OR HERE
}
}
这意味着你应该超出列表末尾,并在while循环中进行比较:
while (++it != tableAndHand.end())
永远产生真,因为迭代器永远不会指向容器的末尾完全。
如果元素的数量是偶数, 可以工作(尽管,因为你有时会删除元素,所以很难预测)。
另一个问题是,初始迭代将立即递增it
一次,如果容器恰好为空,则立即将其推送到容器的末尾。
答案 2 :(得分:1)
if(*it == *(--it))
此代码的行为未指定:编译器可以在比较的右侧评估--it
,然后评估左侧的it
,或者它可以执行它们反过来说。
更一般地说,对于列表,不要尝试使用相同的迭代器来访问两个相邻的元素;它只会导致令人困惑的代码。使用两个迭代器:当前位置和尾部,每次递增一次,每次循环时只递增一次。