remove_if有两种,一种是list等容器的方法list::remove_if,另一种是泛型算法中的remove_if方法,原型就不详细说了,可以去查MSDN。
其中list::remove_if只有一个参数,即一个一元谓词,为真时执行删除操作,这里的“删除”是真正删除了元素项,无需在后续中使用erase()方法,而且函数没有返回值;而泛型算法的remove_if方法可以设定删除范围,比如对于list容器v,remove_if(v.begin(), v.end(), p(x)),前两个参数就是容器v的范围,而最后一个参数就是一元谓词,这个和list::remove_if相同的。但是,这里的删除并没有真正删除了元素项,只是满足条件的元素被后续不满足条件的元素覆盖了,容器尾部还有重复的元素项存在,需要利用erase()删除,删除时可以利用函数的返回值,返回的是指向容器有效项末尾的迭代器;
以下是我的测试代码,测试环境为vs.net2008:
#include "stdafx.h"
#include "TestSTL_001.h"
#include <list>
#include <algorithm>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
//bool Judge(int &n);
bool Judge(int &n1, int &n2);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed/n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
int i;
list<int> v;
list<int>::iterator jt;
//list<int>::iterator ut;
for(i=0; i<=20; i++)
{
v.push_back(i);
}
for(i=0, jt = v.begin(); i<5; i++, jt++);
cout << "初始长度:" << v.size() << "/n";
list<int>::iterator ut;
list<int>::iterator vt;
list<int>::iterator it = v.begin();
//使用泛型算法中的remove_if可以指定范围,但是无法真正删除元素项,返回指向的末尾项
ut = remove_if(jt, v.end(), Judge);
for(vt=ut; vt!=v.end();)
{
//vt = v.erase(vt); //这个算法是正确的,返回指向下一元素的迭代器
v.erase(vt++); //这个算法也是正确的
//v.erase(vt); vt++; //这个算法是错误的,vt在v.erase后就失效了
}
//使用list::remove_if()只允许有“谓词”一个参数,但是真正删除了元素项
//v.remove_if(Judge);
cout << "After remove_if: " << v.size() << "/n";
for(it = v.begin(); it != v.end(); )
{
cout << " " << *it;
++it;
}
/*jt++;
cout << *jt;*/
}
return nRetCode;
}
bool Judge(int &n1, int &n2)
{
n2 = 0;
if(n1%5==0)
return true;
else
return false;
}