在类似圆桌循环遍历,然后逐个弹出元素的问题上遇到了两个程序错误,
第一个是 list iterator dereferenable的问题
因为逐个删除元素的过程中,有两种写法让迭代器 it 重新指向list的下一个元素
list<int> q;
list<int> :: iterator it ;
1,it = q.erase(it),
这里it 被删除后,it会自动指向下一个元素,然后重新赋给it;
2,q.erase(++it) ;
++it 的道理很简单,即 it = it +1;++it 返回的值是没有加1的那个值,删除后,it将变成it+1这个值
那么,在圆桌问题删除元素的过程中,就有可能在list容器已经位空的的时候还在进行圆桌循环遍历,这个就是出现 list iterator dereferenable 问题的原因。解决的方法就是在删除元素的下一行多加一条判断语句 if(q.empty) break 我遇到问题的时候虽然也加了这条语句,但是,并没有加在删除代码的下一行,所以导致了程序错误;
第二个问题就是 list iterator incrememtable
这个问题其实就是一个 迭代器指向失效的问题
我上面的两种删除后it重新赋值的方法其实在个别问题上是存在一些缺陷的,
圆桌循环的关键语句是 if(it == q.end()) it = q.begin(); 就是当it指向list容器最末尾的时候,在重新将it迭代器指向list容器的开头来达到一个圆桌循环的过程,那么 在循环过程中用到的 for循环,很多人都习惯的喜欢把 ++it 写在for循环的括号里
for( it = q.begin() ; ; ++it) 像这样,但是,这样的写法可能会出现一些问题,就是,当it = q.end() 是没有任何值得,是一个空值,如果把这个空值带进循环内执行,就会出现一些问题,那么最安全得写法就是把 ++it 单独放出来(代码的目的可以忽视)
if (num == cnt) {
cout << *it << endl;
num = 0;
it = q.erase(it);
if (q.empty()) break; //删除元素后下一行开始判断是否位空,因为删除后 it就自动指向下一个了,所以不需要在而外的it++
}
else {
++it; //++it 单独拿出,下一行加上是否已经到list容器的底部
if (it == q.end()) it = q.begin();
}