如何删除std::vector内的element?(使用for loop) (中级)

初学者若想要删除std::vector内的element,第一个想到的就是用for loop,若该iterator的值是我要删的,就erase


1 None.gif //  Compile OK, but run-time error!!
2 ExpandedBlockStart.gifContractedBlock.gif for (std::vector < int > ::iterator iter  =  ivec.begin(); iter  !=  ivec.end();  ++ iter)  dot.gif {
3ExpandedSubBlockStart.gifContractedSubBlock.gif  if (*iter == 8dot.gif{
4InBlock.gif    ivec.erase(iter);
5ExpandedSubBlockEnd.gif  }

6ExpandedBlockEnd.gif}


以上的程序,compile可过,但run-time无法执行,为什么呢?若用debug的watch观察,发现iter被erase后,该iter会指向一个不可预期的地址,导致++iter错误,若要用for loop,必须改成以下写法


 1 ExpandedBlockStart.gif ContractedBlock.gif /**/ /* 
 2InBlock.gif(C) OOMusou 2006 http://oomusou.cnblogs.com
 3InBlock.gif
 4InBlock.gifFilename    : VectorFindAndEraseByForLoop.cpp
 5InBlock.gifCompiler    : Visual C++ 8.0
 6InBlock.gifDescription : Demo how to erase iterator by For Loop.
 7InBlock.gifRelease     : 11/14/2006
 8ExpandedBlockEnd.gif*/

 9 None.gif#include  < iostream >
10 None.gif#include  < vector >
11 None.gif
12 ExpandedBlockStart.gifContractedBlock.gif int  main()  dot.gif {
13InBlock.gif  const int iaSize = 11;
14ExpandedSubBlockStart.gifContractedSubBlock.gif  int ia[] = dot.gif{011235813215589};
15InBlock.gif
16InBlock.gif  std::vector<int> ivec;
17InBlock.gif  ivec.insert(ivec.end(), ia, ia + iaSize);
18InBlock.gif
19InBlock.gif   // Compile OK, but run-time error!!
20InBlock.gif   //for(std::vector<int>::iterator iter = ivec.begin();
21InBlock.gif   // iter != ivec.end(); ++iter) {
22InBlock.gif   //   if (*iter == 8) {
23InBlock.gif   //     ivec.erase(iter);
24InBlock.gif   //   }
25InBlock.gif   //}
26InBlock.gif
27InBlock.gif  // Compile OK, run-time OK!!
28InBlock.gif  for(std::vector<int>::iterator iter = ivec.begin();
29ExpandedSubBlockStart.gifContractedSubBlock.gif    iter != ivec.end(); ++iter) dot.gif{
30ExpandedSubBlockStart.gifContractedSubBlock.gif      if (*iter == 8dot.gif{
31InBlock.gif        --(iter = ivec.erase(iter));
32ExpandedSubBlockEnd.gif      }

33ExpandedSubBlockEnd.gif  }
 
34InBlock.gif 
35InBlock.gif  // cout the result
36InBlock.gif  for(std::vector<int>::const_iterator iter = ivec.begin();
37ExpandedSubBlockStart.gifContractedSubBlock.gif    iter != ivec.end(); ++iter) dot.gif{
38InBlock.gif
39InBlock.gif      std::cout << *iter << std::endl;
40ExpandedSubBlockEnd.gif  }

41InBlock.gif
42InBlock.gif  return 0;
43ExpandedBlockEnd.gif}


vector.erase()删除iterator后,会传回下一个iterator的pointer,若在由for loop的++iter,则会少考虑了被删除后的下一个iterator,故需加上--,将iterator往前移,移到被删除的iterator的前一个iterator,这样for loop的++iterator才会考虑到被删除的下一个iterator。


为了证明这个方法可行,而不是只适用于vector(因为常发现vector可跑的程序,在其它container却不能跑),特别将原程序改成list,证明此法正确。

 1 ExpandedBlockStart.gif ContractedBlock.gif /**/ /* 
 2InBlock.gif(C) OOMusou 2006 http://oomusou.cnblogs.com
 3InBlock.gif
 4InBlock.gifFilename    : ListFindAndEraseByForLoop.cpp
 5InBlock.gifCompiler    : Visual C++ 8.0
 6InBlock.gifDescription : Demo how to erase iterator by For Loop.
 7InBlock.gifRelease     : 11/14/2006
 8ExpandedBlockEnd.gif*/

 9 None.gif#include  < iostream >
10 None.gif#include  < list >
11 None.gif
12 ExpandedBlockStart.gifContractedBlock.gif int  main()  dot.gif {
13InBlock.gif
14InBlock.gif  std::list<int> ilist;
15ExpandedSubBlockStart.gifContractedSubBlock.gif  for(int i = 0; i != 10++i) dot.gif{
16InBlock.gif    ilist.push_back(i);
17ExpandedSubBlockEnd.gif  }

18InBlock.gif
19InBlock.gif   // Compile OK, but run-time error!!
20InBlock.gif   //for(std::list<int>::iterator iter = ilist.begin();
21InBlock.gif   // iter != ilist.end(); ++iter) {
22InBlock.gif   //   if (*iter == 8) {
23InBlock.gif   //     ilist.erase(iter);
24InBlock.gif   //   }
25InBlock.gif   //}
26InBlock.gif
27InBlock.gif   for(std::list<int>::iterator iter = ilist.begin();
28ExpandedSubBlockStart.gifContractedSubBlock.gif    iter != ilist.end(); ++iter) dot.gif{
29ExpandedSubBlockStart.gifContractedSubBlock.gif      if (*iter == 8dot.gif{
30InBlock.gif        --(iter = ilist.erase(iter));
31ExpandedSubBlockEnd.gif      }

32ExpandedSubBlockEnd.gif   }

33InBlock.gif 
34InBlock.gif  // cout the result
35InBlock.gif  for(std::list<int>::const_iterator iter = ilist.begin();
36ExpandedSubBlockStart.gifContractedSubBlock.gif    iter != ilist.end(); ++iter) dot.gif{
37InBlock.gif
38InBlock.gif      std::cout << *iter << std::endl;
39ExpandedSubBlockEnd.gif  }

40InBlock.gif
41InBlock.gif  return 0;
42ExpandedBlockEnd.gif}

 


其实这并不是建议的方式,只是demo若还是要用for loop写,该怎么改成可以执行的程序,但可以发现程序相当的『丑』,修修补补的痕迹非常明显,正规的作法该用find()这个generic algorithm找到要删除的iterator后,直接删除,请参阅如何删除std::vector内的element?(使用find) (初级)

See Also
如何删除std::vector内的element?(使用find) (初级)

void IntersectionInfoCache::makePolygonDrawData(std::vector<GeoLocation>& vecPoints, std::vector<uint16>& triangleIndexList, uint8 drawelement, //多边形描画数据 vector<IntersectionImageData>& imageData) { std::vector<PolygonTessVertex> points; uint32 pointcount = vecPoints.size(); points.reserve(pointcount); for(int32 i = 0;i < pointcount;++i) { PolygonTessVertex m_point; m_point.vertex.x = vecPoints[i].longitude; m_point.vertex.y = vecPoints[i].latitude; points.emplace_back(m_point); } TessPolygon(points, triangleIndexList); std::vector<GeoLocation> vecTessPoints; uint32 pointcountTess = points.size(); vecTessPoints.reserve(pointcountTess); for(int32 i = 0;i < pointcountTess;++i) { GeoLocation m_point; m_point.longitude = points[i].vertex.x; m_point.latitude = points[i].vertex.y; vecTessPoints.emplace_back(m_point); } IntersectionImageData tempimagedata; tempimagedata.drawelement = drawelement; tempimagedata.vertex.assign(vecTessPoints.begin(), vecTessPoints.end()); tempimagedata.index.assign(triangleIndexList.begin(), triangleIndexList.end()); imageData.emplace_back(tempimagedata); } void TessPolygon(std::vector<PolygonTessVertex> &points, std::vector<uint16> &triangleIndexList) { auto uiPointCount = points.size(); GLUtesselator* tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)PolygonVertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)PolygonBeginCallback); gluTessCallback(tobj, GLU_TESS_END_DATA, (_GLUfuncptr)PolygonEndCallback); gluTessCallback(tobj, GLU_TESS_ERROR_DATA, (_GLUfuncptr)PolygonErrorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)PolygonCombineCallback); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); PolygonData_t stPolygonData; gluTessBeginPolygon(tobj, &stPolygonData); gluTessBeginContour(tobj); /* for loop statement: the initial value of decltype(uiPointCount) Index is 0 / for(decltype(uiPointCount) Index = 0; Index < uiPointCount; ++Index) { stPolygonData.vecVertexArray.emplace_back(points[Index]); TessPolygonVertex tempTessVertex; tempTessVertex.location[0] = points[Index].vertex.x; tempTessVertex.location[1] = points[Index].vertex.y; gluTessNormal(tobj, 0.0, 0.0, 1.0); gluTessVertex(tobj, tempTessVertex.location, (GLvoid)Index); } gluTessEndContour(tobj); gluTessEndPolygon(tobj); gluDeleteTess(tobj); points.swap(stPolygonData.vecVertexArray); triangleIndexList.swap(stPolygonData.vecDrawIndices); }加上注释
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值