Clause 19 删除元素的方法
1、对于连续内存的容器(vector,dequeu,string),最好的方法是用erase - remove
c.erase(remove(c.begin(),c.end(),1963),c.end());
/* remove(first,end,value) : The remove algorithm removes all elements that match value from the range (First, Last). It returns an iterator equal to Last - n, where n = number of elements removed. That is ,if c is {3,2,1963,12,1963,16}, after remove , c is {3,2,12,16,1963,1963}.*/
2、对于list,c.remove(1963);
3、对于关联容器(map,set) 可以用c.erase(1963); 而且开销是对数时间的。而前两条中的开销是线性的。
3、如果是要删除满足某一条件的值,对于连续内存的容器(vector,dequeu,string),用erase - remove_if。对于list,用remove_if
c.erase(remove_if(c.begin(),c.end(),yourcondition),c.end()); /*删除使youcondition为true的值*/
4、对于关联容器,必须遍历整个容器中的元素了。
下面是重点:
下面的程序是不对的
AssocContainer < int > c;
for (AssoContainer < int > ::iterator i = c.begin();i != c.end();i ++ )
if (youcondition( * i)) c.erase(i);
因为当把i删除后,i就变成了无效的值。这样,后面的i++就无效了。
解决这个问题的最简单的方法是:
5、第4条所述的方法,只对关联容器起作用。对于vector,string,dequeu,上面的方法会出错。因为这类容器,当删除一个元素后,不仅指向被删除的元素的迭代器无效,也会使被删除元素之后的所有的迭代器失效。
这时,我们要用erase的返回值。erase返回被删除元素的下一个元素的有效的迭代器。
因此可以这样
还要注意,对于关联容器,erase返回void.
总结:
c.erase(remove(c.begin(),c.end(),1963),c.end());
/* remove(first,end,value) : The remove algorithm removes all elements that match value from the range (First, Last). It returns an iterator equal to Last - n, where n = number of elements removed. That is ,if c is {3,2,1963,12,1963,16}, after remove , c is {3,2,12,16,1963,1963}.*/
2、对于list,c.remove(1963);
3、对于关联容器(map,set) 可以用c.erase(1963); 而且开销是对数时间的。而前两条中的开销是线性的。
3、如果是要删除满足某一条件的值,对于连续内存的容器(vector,dequeu,string),用erase - remove_if。对于list,用remove_if
c.erase(remove_if(c.begin(),c.end(),yourcondition),c.end()); /*删除使youcondition为true的值*/
4、对于关联容器,必须遍历整个容器中的元素了。
下面是重点:
下面的程序是不对的
AssocContainer < int > c;
for (AssoContainer < int > ::iterator i = c.begin();i != c.end();i ++ )
if (youcondition( * i)) c.erase(i);
因为当把i删除后,i就变成了无效的值。这样,后面的i++就无效了。
解决这个问题的最简单的方法是:
5、第4条所述的方法,只对关联容器起作用。对于vector,string,dequeu,上面的方法会出错。因为这类容器,当删除一个元素后,不仅指向被删除的元素的迭代器无效,也会使被删除元素之后的所有的迭代器失效。
这时,我们要用erase的返回值。erase返回被删除元素的下一个元素的有效的迭代器。
因此可以这样
SeqContainer
<
int
>
c;
for (SeqContainer < int > ::iterator i = c.begin();i != c.end();)
{
if (youcondition( * i))
{
dosomething( * it);
i = c.erase(i);
}
else i ++ ;
}
for (SeqContainer < int > ::iterator i = c.begin();i != c.end();)
{
if (youcondition( * i))
{
dosomething( * it);
i = c.erase(i);
}
else i ++ ;
}
还要注意,对于关联容器,erase返回void.
总结:
● 去除一个容器中有特定值的所有对象:
如果容器是vector、string或deque,使用erase-remove惯用法。
如果容器是list,使用list::remove。
如果容器是标准关联容器,使用它的erase成员函数。
● 去除一个容器中满足一个特定判定式的所有对象:
如果容器是vector、string或deque,使用erase-remove_if惯用法。
如果容器是list,使用list::remove_if。
如果容器是标准关联容器,使用remove_copy_if和swap,或写一个循环来遍历容器元素,当你把迭代器传给erase时记得后置递增它。
● 在循环内做某些事情(除了删除对象之外):
如果容器是标准序列容器,写一个循环来遍历容器元素,每当调用erase时记得都用它的返回值更新你的迭代器。
如果容器是标准关联容器,写一个循环来遍历容器元素,当你把迭代器传给erase时记得后置递增它。