读书人

钻个器皿erase的牛角尖(欢迎指导)

发布时间: 2013-02-24 17:58:56 作者: rapoo

钻个容器erase的牛角尖(欢迎指导)
今日工作遇到一个问题,以前一直使用以下方法中的第一种方式,连续删除关联容器元素,今日突然得见第二种方式,被告知第一种在erase的后迭代器有可能失效,此时迭代器再自加则会崩溃,貌似有些道理,所以小弟在此请教下,求解迷津。


//第一种
AssocContainer<int> c;
...
for (AssocContainer<int>::iterator i = c.begin(); i != c.end();)
{
if (badValue(*i))
c.erase(i++); // 对于坏的值,把当前的
else
++i; // i传给erase,然后
} // 作为副作用增加i;对于好的值,只增加i

//第二种
AssocContainer<int> c;
...
for (AssocContainer<int>::iterator i = c.begin(); i != c.end();)
{
AssocContainer<int>::iterator iTemp = i++;
if (badValue(*i))
c.erase(i); // 对于坏的值,把当前的
}
STL?迭代器?erase
[解决办法]
iter = c.earse(..);

可以通过earse的返回值保存下个有效的iter.

或者用erase(remove....) 惯用方法.
[解决办法]
先不说第一种和第二种erase的对象根本就不一样
你这2种方法根本就没有本质上的差别吧,erase完成后的i都是erase前的i自增后的结果

这段代码应该是effective stl上的,AssocContainer是指某一种关联容器,关联容器是有保证删除某个元素后迭代器不失效的

而对于序列容器,应该用1楼的方法,而不是lz的方法2,而这也是在effective stl里有写的
[解决办法]
iterator i 定义i为迭代器,看着真别扭
[解决办法]
第一个是正确的.
[解决办法]
引用:
第二种写错了。。粗心了
C/C++ code?1234567891011121314151617181920212223242526//第一种 AssocContainer<int> c; ... for (AssocContainer<int>::iterator iter = c.begin(); iter != c.end();) { if (b……



第一种, I 会先自增然后再进入erase函数. 没有问题.

[解决办法]
vector<int> vec;
for(vector<int>::iterator iter = vec.begin(); iter != vec.end();)
{
if(bad) iter = vec.erase(iter);
else ++iter;
}
[解决办法]
Quote: 引用:

c.erase(iter++); // 我同事的意思是,这里i是先被erase的,
//关联容器这个i是不是在erase之
//后被释放呢?然后才执行的自增,如果i已经失效,
//则有可能导致崩溃,如果
//不崩溃,则是没失效,具体估计就得开代码实现了

Quote:

不知道是你写错了还是你和你同事根本没理解后置++的含义
iter++是对iter自增然后返回一个自增前的值,是先自增然后再erase的
erase后指向被删除的结点的迭代器自然是失效的,但是其他迭代器都是有效的
[解决办法]
对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

[解决办法]
两种方法都没有问题啊。

但是个人习惯用8楼的方法

引用:
vector<int> vec;
for(vector<int>::iterator iter = vec.begin(); iter != vec.end();)
{
if(bad) iter = vec.erase(iter);
else ++iter;
}

[解决办法]
Should use std::remove_if algorithm easily instead of looping through the entire container. As Associated container is sorted already, isn't it faster by using std::remove_if? Also it has less chance to have invalid iterator because you don't use it explicitly.

AssocContainer<int> c;
std::remove_if(c.begin(), c.end(), [](int i){ return badValue(i); });

[解决办法]
两种写法本质是一样的。用在list类型的没有问题,vector类型的就不行了。
一般用remove_if比较好

AssocContainer<int>::iterator remove_end = remove_if(c.begin(), c.end(), [](int elm){return badValue(elm);});
c.erase(remove_end, c.end());

[解决办法]
引用:
两种写法本质是一样的。用在list类型的没有问题,vector类型的就不行了。
一般用remove_if比较好
C/C++ code?12AssocContainer<int>::iterator remove_end = remove_if(c.begin(), c.end(), [](int elm){return badValue(elm);});c.erase……


He is talking about associative container, you don't need to use remove erase idiom.
[解决办法]
不太清楚关联容器以及erase的内部实现,第二种较第一种更靠谱一点。
[解决办法]
标准的STL关联式容器包括:set、multiset、map、multimap。
vector list什么的不是啊童鞋们。
另外删除关联容器元素的时候其他元素的迭代器不会受影响,这两种方法都可以的。

[解决办法]
引用:
标准的STL关联式容器包括:set、multiset、map、multimap。
vector list什么的不是啊童鞋们。
另外删除关联容器元素的时候其他元素的迭代器不会受影响,这两种方法都可以的。

最后一句话错了,应该使用std::remove_if. 如果你的map/set 有1百万单元, 你全部循环一遍??
[解决办法]
楼主,别钻了,买本effective stl认真啃啃
你现在问的,和即将问的,上面都有现成答案了。

读书人网 >C++

热点推荐