??xml version="1.0" encoding="utf-8" standalone="yes"?>
Lua中Metatableq个概念, 国内他译为元? 元表为重定义Lua中Q意一个对??的默认行为提供了一U公开入口. 如同许多OO语言的操作符重蝲或方法重? Metatable能够为我们带来非常灵zȝ~程方式.
具体的说, Lua中每U类型的值都有都有他的默认操作方? ? 数字可以做加减乘除等操作, 字符串可以做q接操作, 函数可以做调用操? 表可以做表项的取D值操? 他们都遵循这些操作的默认逻辑执行, 而这些操作可以通过Metatable来改? ? 你可以定?个表如何相加{?
看一个最单的例子, 重定义了2个表的加法操? q个例子中将c的__add域改写后a的Metatable讄为c, 当执行到加法的操作时, Lua首先会检查a是否有Metatableq且Metatable中是否存在__add? 如果有则调用, 否则检查b的条?和a相同), 如果都没有则调用默认加法q算, 而table没有定义默认加法q算, 则会报错.
有了个感性的认识? 我们看看Metatable的具体特?
Metatableq不秘, 他只是一个普通的table, 在tableq个数据l构当中, Lua定义了许多重定义q些操作的入? 他们均以双下划线开头ؓtable的域, 如上面例子的__add. 当你Z个D|了Metatable, q在Metatable中设|了重写了相应的操作? 在这个值执行这个操作的时候就会触发重写的自定义操? 当然每个操作都有每个操作的方法格式签? 如__add会将加号两边的两个操作数做ؓ参数传入q且要求一个返回? 有h把这L行ؓ比作事g, 当xx行ؓ触发会激zM件自定义操作.
在Lua中Q何一个值都有Metatable, 不同的值可以有不同的Metatable也可以共享同LMetatable, 但在Lua本n提供的功能中, 不允怽改变除了tablecd值外的Q何其他类型值的Metatable, 除非使用C扩展或其他库. setmetatable和getmetatable是唯一一l操作tablecd的Metatable的方?
Metatable与面向对?/strong>
Lua是个面向q程的语a, 但通过Metatable可以模拟出面向对象的样子. 其关键就在于__indexq个? 他提供了表的索引值入? q很像重写C#中的索引? 当表要烦引一个值时如table[key], Lua会首先在table本n中查找key的? 如果没有q且q个table存在一个带有__index属性的Metatable, 则Lua会按照__index所定义的函数逻辑查找. 仔细x, q不正ؓ面向对象中的核心思想l承, 提供了实现方式么. Lua中实现面向对象的方式非常? 但无论哪U都M开__index.
q个例子中我使用了Programming In Lua中的实现OO的方? 建立了Bird(?对象, 拥有会飞的属? 其他鸟对象基于此原型, Ostrich(鸵鸟)是鸟的一U但不会? l果很明? Bird和Ostrich分别有独立的状?
下蝲源代码:http://www.lua.org/ftp/lua-5.2.1.tar.gz
解压备用?span style="padding: 0px; margin: 0px;">q里说句题外话,lauxlib.h ?nbsp;lauxlib.c 我认Z应该是官方的pQ本意应该是 luaxlib.h ?luaxlib.c 吧?
新徏一?static library 工程Q把解压得到的目录下的src子目录中的所?h?c文g拯到新工程目录下?/p>
工程中删除自动生成的 main.c 文gQ添加进除lua.c、luac.c?/span>lua.hpp?/span>的所?h?c文g?/p> ~译Q得?nbsp;libLua.a x库。注意,如果你没有重设过输出目录Q这?liblua.a 文g应该在你的源代码目录里?/span> 然后?nbsp;libLua.a 攑ֈ~译器的 Lib 目录下,?nbsp; lauxlib.h、lua.h、luaconf.h、lualib.h 攑ֈ~译器的 include 目录下(C++用户再添加个 lua.hppQ,最好新Z lua 子目录存攑֤文g更清晰?/span> 另外要注意:lua 5.2.1 创徏一个指向Lua解释器的指针的函?nbsp;lua_open 修改?luaL_newstate?br style="padding: 0px; margin: 0px;" />x工程从lua5.1库{?.2库时Q在调用 lua_open() 的地斚w需要修?/span>?luaL_newstate()?/p> 最q在与一位ȝ理交的时候,他谈C们公司的软g研发理Q说Q?#8220;我们公司最大的问题是项目不能按时完成,总要一拖再拖?#8221;他问我有什么办法能改变q个境况。从q样一个问题开始,在随后的交谈中,又引Z一q串在Y件研发管理中的遇到的问题Q包括: . 现有代码质量不高Q新来的开发h员接手时宁愿重写Q也不愿意看别h留下?#8220;?#8221;代码Q怎么办? . 重构会造成回退Q怎样避免Q?/strong> . 有些开发h员水q相对不高,如何保证他们的代码质量? . 软g研发到底需不需要文档? . 要求提交代码前做Code ReviewQ而开发h员不做,或敷衍了事,怎么办? . 当有开发h员在开发过E中遇到NQ工作无法l,因而拖延进度,怎么解决Q?/strong> . 如何提高开发h员的主观能动性? 其实Q每个Y件研发团队的理者都面着或曾l面临过q些问题Q也都有着自己的管?#8220;套\”来应对这些问题。我把我?#8220;套\”再此i叨i叨?/p> 1. 目不能按时完成Q总要一拖再拖,怎么改变Q?/strong> 找解军_法前Q当然要先知道问题ؓ什么会出现。这位ȝ理说Q?#8220;M不断地有需求要改变和新需求提出来Q原来的开发计划不得不廉?#8221;原来如此。知道根源,当然解决办法也就有了Q那是“敏捷”。敏捷开发因其P代(IterativeQ和增量QIncrementalQ的思想与实践,正好适合“需求经常变化和增加”的项目和产品。在我讲qC敏捷的一些概念,特别是Scrum的框架后Qȝ理也表示了对“敏捷”的认同?/p> 其实仔细xQ这里面q有一个非常普遍的问题。对于品的交付旉或项目的完成旉Q往往由高U管理层Ҏ市场情况决策和确定。在很多软g企业中,q些决策者在决策时往往忽略了一个重要的参数Q那是团队的生产率QVelocityQ。生产率需要量化,而不?#8220;拍脑门子”感觉出来的。敏捷开发中有关于如何估生产率的方法。所以用敏P在估品交付时间或目完成旉Ӟ是相对较准确的。Scrum创始Z一的Jeff Sutherland_他在一个风险投资团队做敏捷教练Ӟ团队中的资深合伙Z向所有的待投资企业问同一个问题:“你们是否清楚团队的生产率Q?#8221;而这些企业都很难做出明确的答复。Y件企业要想给产品定一个较实际的交付日期,首先要弄清楚自q软g生率?/p> 2. 现有代码质量不高Q新来的开发h员接手时宁愿重写Q也不愿意看别h留下?#8220;?#8221;代码Q怎么办? q可能是很多软g开发工E师都有q的体验Q在接手别h的代码时Q看不懂、无法加新功能,M码读的头疹{这说明什么?排除接手Z人水q的因素Q这说明旧代码可L、可扩展性比较差。怎么办?q时Q也讔R构是一U两全其的办法。接手h重构代码Q既能改善旧代码的可L和可扩展性,又不至于因重写代码带来的旉上的风险?/p> 从接手h心理的角度看Q重构还有一个好的副作用Q就是代码重构之后,接手得那些原来的“?#8221;代码被修Ҏ己引以自豪的新成。《Scrum敏捷软g开发》的作者Mike Cohn写到q:“我的奛_们画了一q特别o叹的C后,她们会将它从学校带回Ӟq想把它展示在一个明昄位置Q也是冰箱上面。有一天,在工作中Q我用C++代码实现了某个特别有用的{略模式的程序。因为我认定冰箱门适合展示我们引以的Q何东西,所以我将它放上去了。如果我们一直对自己工作的质量特别自豪,可以骄傲地将它和孩子的艺术品一样展C在冰箱上,那不是很好吗Q?#8221;所以这个积极的促进作用Q将使得接手人感觉修改的代码是自q了,而且期望能够扑ֈ更多的可以重构的东西?/p> 3. 重构会造成回退Q怎样避免Q?/strong> 重构实很容易造成回退QRegressionQ。这Ӟ重构会vC其初L反的作用。所以我们应该尽可能多地增加单元试。有些老品,旧代码,可能没有或者没有那么多的单元测试。但我们臛_要在重构前,增加对要重构部分代码的单元测试。基于重构目的的单元试Q应该遵循以下的原则Q见《重构》第4章:构筑试体系Q: - ~写未臻完善的测试ƈ实际q行Q好q对完美试的无等待。测试应该是一U风险驱动行为,所以不要去试那些仅仅d一个值域的访问函敎ͼ应ؓ它们太简单了Q不大可能出错?/p> - 考虑可能出错的边界条Ӟ把测试火力集中在哪儿。扮?#8220;E序公敌”Q纵容你心智中比较促狭的那一部分Q积极思考如何破坏代码?/p> - 当事情被公认应该会出错时Q别忘了查是否有异常如期被抛出?/p> - 不要因ؓ“试无法捕捉所有Bug”Q就不撰写测试代码,因ؓ试的确可以捕捉到大多数Bug?/p> - “花合理时间抓出大多数Bug”要好q?#8220;I尽一生抓出所有Bug”。因为当试数量辑ֈ一定程度之后,试效益׃呈现递减态势Q而非持箋递增?/p> 说到《重构》这本书Q其实在每个重构Ҏ中都?#8220;作法QMechanicsQ?#8221;一D,在重构的实践中按照上面所q的步骤q行是比较稳妥的Q同时也能避免很多不l意间制造的回退出现?/p> 4. 要求提交代码前做Code ReviewQ而开发h员不做,或敷衍了事,怎么办? 如果每个开发h员都是积极主动的QCode Review的作用能落到实处。但如果不是呢?团队理者需要一些手D促使其有效地进行Code Review。首先,我们采用的Code Review?UŞ式,一是Over-the-shoulderQ也是2个h座在一P一个hԌ另一个h审查。二是用工具Code Collaborator来进行。无论哪UŞ式,在提交代码时Q必L明关于审查的信息Q比如:审查者(ReviewerQ的名字或审查号QReview IDQCode Collaborator自动生成Q,每天׃名专职h员来查Checklist中的每一条,看是否有人漏写这些信息,如果发现会提醒提交的上。另外,某段提交的代码出问题Q提交者和审查者都要一h解决出现的问题,以最大限度避免审查过E敷衍了事?/p> 博主Inovy在某个评的很形象Q?#8220;木(没)有赏|的制度Q就是带到厕所的报U,看完可以用来擦屁股了?#8221;没有奖惩制度作保证,当然上面的要求没有什么效力。所以,当有人经怸审查提交,或审查时不负责QQ它的W效评定就会因此低一点,而W效的评分是跟每年工资涨落挂钩的。说白了Q可能某个h会因为多ơ被查出没有做Code Review提交代码,而到q底加薪时比别h涨500块钱?/p> 5. 软g研发到底需不需要文档? 软g研发需要文档的起原可能?U,一是比较原始的Q需要文档是Z当开发h员离职后Q企业需要接手的Ҏ文档了解他所接手的代码或模块的设计。二是较高层ơ的Q企业遵从ISO9001质量理体系或CMMI?/p> 对于W一U,Ҏ可能来自于两个方面: - 原开发h员设计编码水q不高,其代码可L较差?/p> - 设计思想和代码只有一个h了解Q此Z旦离职,无h知道其细节?/p> 在编码前写一些简单的设计文档Q有助于理清思\Q尤其是辅以一些UML图,在交时也是有好处的。但同时Q我们也应该提高开发h员的~码水^增加其代码的可读性,比如增强其变量命名的可读性、用一些被大家所了解的设计模式来替代按自己某些独Ҏ\~写的代码、增加和改进注释{等Q以减少不必要的文档。另外推行代码的集体所有权QCollective OwnershipQ,避免某些代码只被一个h了解Q这样可以减以此ؓ目的而编写的文档?/p> 对于W二U,情况有些复杂。接触过敏捷开发的人都知道《敏捷宣a》中?#8220;可以工作的Y件胜于面面俱到的文档”。接触过CMMI开发或者ISO9001质量理体系的h知道它们Ҏ档的要求是多么的高。它们看h水火不相宏V但是,它们的宗旨是一致的Q即Q构建高质量的品?/p> 对于敏捷Q用手写用h事来记录需求和优先U的ҎQ以及在白板上写ȝ非正式设计,是不能通过ISO9001的审核的Q但当把它们复印、拍照、增加序受保存后Q可以通过审核。每ơ都是成功的Daily Build和Auto Test报告无法证明它们是否真正被执行ƈ真正成功Q所以不能通过ISO9001的审核。但d一个断ap|Q类似assert(false)的断aQ的试后,则可以通过审核?/p> CMMI与敏捷也是互补的Q前者告诉组l在M条款上做什么,但是没有说如何去做,后者是一套最佛_cSCRUM之类的敏h法也被引入过那些已通过CMMI5U评估的l织。很多企业忘C最l目标是改进他们构徏软g及递交产品的方式,相反Q它们关注于填写按照CMMI文档描述的假想的~陷Q却不关心这些变化是否能改进q程或品?/p> 所以敏捷开发在q程中只~写够用的文档,和以“信息的沟通、符合性的证据以及知识׃n”作ؓ主要目标的质量体pL档要求ƈ不矛盾。在实践中,我们可以按以下方法做Q在实现SCRUM的同ӞW合审核和评估的要求Q?/p> - 制作格式良好的、被l化的、被保存的和能跟t的Backlog。复印和照片同样有效?/p> - 监需要的文档工作也放入Backlog。除了可以确保它们不被忘讎ͼq能使监要求的成本是可见的?/p> - 使用查列表,以向审核员或评估员证明活动已执行。团队对“完成”的定?Definition of “Done”)可以很容易{变ؓ一份检查列表?/p> - 使用敏捷目理工具。它其实是开发程序和记录的电子呈现方式?/p> 总而言之,软g研发需要文档(但文档的形式可以是多U多LQ用Word写的文字式的文g是文档,用VisioȝUML图也是文档,保存在Quality Center中的试用例也是文档Q,同时我们只需写够用的文档?/p> 6. 当有开发h员在开发过E中遇到NQ工作无法l,因而拖延进度,怎么解决Q?/strong> q也是个帔R到的问题。如果管理者对于某个工E师的具体问题进行指|׃陷入q度微观理的境地。我们需要找到宏观解军_法。一Q我们基于Scrum?#8220;团队有共同的目标”q一规则Q利用前面提到的集体所有权Q当出现q些问题Ӟ用团队中所有可以用的力量来帮助其摆脱困境Q而不是Q其他手旁观。当然这里会牉|到W效评定的问题Q比如:提供帮助的h会觉得,他的帮助无助于自qW效评定的提高Qؓ什么要提供帮助。这需要h力资源部门在使用Scrum开发的团队的W效评CQ尽量消除那些們个h的因素,q要包含团队协作的因素,q泛听取个方面的意见Q更频繁地评估W效等{?/p> 二,即动用所有可以用的力量Q如果某个难题真的无法逾越Qؓ了减不能按时交付的风险Q品负责h应当站出来,q有所作ؓ。要么重新评估Backlog的优先Q无法l箋的Backlogq一点交付,先做一些相对较低优先的BacklogQ以保证整体交付旉不至于g长;要么减少部分功能Q给出更多的旉L克难题。M逾越技术上隑օ会团队的生产率下降Q品负责h必须作出取舍?/p> 7. 有些开发h员水q相对不高,如何保证他们的代码质量? 当然首先让较有经验的人Review其要提交的代码,q几乎是所有管理者会做的事。除此之外,理者有责Q帮助q些人(也包括水q高的人)提高水^Q他们可以看一些书Q上|看资料Q读别h的代码等{,途经q是很多的。但问题是你如何去衡量其是否真正有所收获。我们的l验是,在每q大U?月䆾为每个工E师制定整个q度的目标,每个人的目标包括产品上的Q技术上的,个h能力上的{??V半q后和一q后Q要做两ơPerformance ReviewQ目标是否实玎ͼ也会跟W效评定挂钩。我们在制定目标Ӟ遵@SMART原则Q即Q?/p> SpecificQ明的Q:目标应该按照明确的结果和成效表述?/p> MeasurableQ可衡量的)Q目标的完成情况应该可以衡量和验证?/p> AlignedQ结盟的Q:目标应该与公司的商业{略保持一致?/p> RealisticQ现实的Q:目标虽然应具挑战性,但更应该能在l定的条件和环境下实现?/p> Time-BoundQ有旉的)Q目标应该包括一个实现的具体旉?/p> 比如Q某个h制定?#8220;初步掌握本地化技?#8221;的目标,他要定实现旉Q要描述学习的途经和步骤,要通过技术施加到公司现有的品中Qؓ公司产品的本地化/国际?全球化作一些探索,q制作Presentationl团队演CZ的成果,q准备回{其他h提出的问题。团队还Z配合其实现目标,l织Tech Talk的活动,供大家分享每个h的学习成果。通过q些手段Q提高开发h员的自学兴趣Qƈ逐步提高开发h员的技术水q?/p> 8. 如何提高开发h员的主观能动性? 提高开发h员的主观能动性,不了激励机制。不能让开发h员感刎ͼ5q以后的他和现在比不会有什么进步。你要让他感C所从事的是一个职业(CareerQ,而不只是一份工作(JobQ。否则,他们是不会主动投入到工作中的。我们的l验是提供一套职业发展的框架。框架制定了2cd展道路,理c(Managerial PathQ和技术类QTechnical PathQ,6个职业别(1-3U是Entry/AssociateQIntermediateQSenior?U管理类是Manager/Senior ManagerQ技术类是Principal/Senior Principal?U管理类是Director/Senior DirectorQ技术类是Fellow/Architect?U是Executive ManagementQ。每个别都?3个方面的具体要求Q包括:范围QScopeQ、跨职能QCross FunctionalQ、层ơ(LevelQ、知识(KnowledgeQ、指|GuidanceQ、问题解冻IProblem SolvingQ、递交成果QDelivering ResultQ、责LQResponsbilityQ、导师(MentoringQ、交(CommunicationQ、自学(Self-LearningQ,q作监督QOperational OversightQ,客户响应QCustomer ResponsivenessQ。每q有2ơ提高别的ZQ开发h员一旦具备了升的条Ӟ他的Supervisor会提出甌Q一旦批准,他的头衔随之提高Q薪水也会有相对较大提高。从而每个开发h员觉?#8220;有奔?#8221;Q自然他们的主观能动性也提高了?/p> 上面?#8220;套\”涉及了Y件研发团队管理中的研发过E、技术实c文档管理、激励机制等一些方面。但只是九牛一毛,研发团队理늛的内容还有很多很多,q需要管理者在不断探烦和实늚道\上学习和掌握?/p>
其实最关键是除开不必要的文gQ实际上Q?br style="padding: 0px; margin: 0px;" />~译 luaQlua.exeQ解析器Q?时删除luac.cQ加入lua.c?br style="padding: 0px; margin: 0px;" />~译 luacQluac.exeQ字节码~译器)时删除lua.cQ加入luac.c?br style="padding: 0px; margin: 0px;" />~译 lib和dllQliblua.a和lua.dllQ库Q时把lua.c和luac.c都删除?/p>
转自Q?a >http://my.oschina.net/u/580100/blog/108468
]]>
SERVICE_STATUS gSvcStatus; //服务状?/span>
SERVICE_STATUS_HANDLE gSvcStatusHandle; //服务状态句?/span>
HANDLE ghSvcStopEvent = NULL;//服务停止句柄
#define SERVER_NAME TEXT("my_server") //服务?/span>
VOID WINAPI Server_main( DWORD, LPTSTR *); //服务入口?/span>
void ServerReportEvent(LPTSTR szName,LPTSTR szFunction); //写Windows日志
VOID ReportSvcStatus( DWORD, DWORD, DWORD ); //服务状态和SCM交互
VOID WINAPI SvcCtrlHandler( DWORD ); //SCM回调函数
VOID ServerProgram(DWORD, LPTSTR *); //服务ȝ?/span>
void main()
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SERVER_NAME, (LPSERVICE_MAIN_FUNCTION)Server_main },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
ServerReportEvent(SERVER_NAME,TEXT("StartServiceCtrlDispatcher"));
}
}
static VOID WINAPI Server_main(DWORD dwArgc, LPTSTR *lpszArgv )
{
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(
SERVER_NAME,
SvcCtrlHandler);
if( !gSvcStatusHandle )
{
ServerReportEvent(SERVER_NAME,TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; //只有一个单独的服务
gSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
// Perform service-specific initialization and work.
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
// Report running status when initialization is complete.
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
ServerProgram(dwArgc, lpszArgv); //你需要的操作在此d代码
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
}
void ServerReportEvent(LPTSTR szName,LPTSTR szFunction)
{
HANDLE hEventSource;
LPCTSTR lpszStrings[2];
unsigned int len = sizeof(szFunction);
TCHAR *Buffer = new TCHAR[len];
hEventSource = RegisterEventSource(NULL, szName);
if( NULL != hEventSource )
{
//StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());
strcpy(Buffer,szFunction);
lpszStrings[0] = szName;
lpszStrings[1] = Buffer;
ReportEvent(hEventSource, // event log handle
EVENTLOG_ERROR_TYPE, // event type
0, // event category
SVC_ERROR, // event identifier
NULL, // no security identifier
2, // size of lpszStrings array
0, // no binary data
lpszStrings, // array of strings
NULL); // no binary data
DeregisterEventSource(hEventSource);
}
}
VOID ReportSvcStatus( DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ( (dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED) )
gSvcStatus.dwCheckPoint = 0;
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{
// Handle the requested control code.
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
return;
case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;
default:
break;
}
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
}
]]>
vector的push_back操作 可能没事Q但是一旦引发内存重分配Q所有P代器都会失效Q?br />vector的insert操作 插入点之后的所有P代器失效Q但一旦引发内存重分配Q所有P代器都会失效Q?br />vector的erase操作 插入点之后的所有P代器失效Q?br />vector的reserve操作 所有P代器失效Q因为它D内存重分配)Q?br />
list/map: 插入不会使得Mq代器失效;删除q算使指向删除位|的q代器失效,但是不会失效其他q代?
deque的insert操作 所有P代器失效Q?br />deque的erase操作 所有P代器失效Q?br />
1. 对于兌容器(如map, set, multimap,multiset)Q?/span>删除当前的iteratorQ仅仅会使当前的iterator失效Q只要在eraseӞ递增当前iterator卛_。这是因为map之类的容器,使用了红黑树来实玎ͼ插入、删除一个结点不会对其他l点造成影响。eraseq代器只是被删元素的q代器失效,但是q回gؓvoidQ所以要采用erase(iter++)的方式删除P代器?br />for (iter = cont.begin(); it != cont.end();)
{
(*iter)->doSomething();
if (shouldDelete(*iter))
cont.erase(iter++);
else
++iter;
}
2. 对于序列式容?如vector,deque)Q删除当前的iterator会后面所有元素的iterator都失效。这是因为vetor,deque使用了连l分配的内存Q删除一个元素导致后面所有的元素会向前移动一个位|。所以不能用erase(iter++)的方式,q好eraseҎ可以q回下一个有效的iterator?br />for (iter = cont.begin(); iter != cont.end();)
{
(*it)->doSomething();
if (shouldDelete(*iter))
iter = cont.erase(iter);
else
++iter;
}
3. 对于list来说Q它使用了不q箋分配的内存,q且它的eraseҎ也会q回下一个有效的iteratorQ因?span style="color: #ff0000;">上面两种Ҏ都可以用?/span>
删除数组中某个元素后q箋重复的元素,例如 1Q?Q?Q?Q?Q?Q?Q?Q?Q? ---> 1Q?2Q?Q?Q?Q?。给出问题的一个正的实现Q?br />
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
int a[] = {1, 1, 3, 3, 3, 2, 4, 1, 1, 1, 0};
int size = sizeof(a)/sizeof(a[0]);
vector<int> vec(a, a+size);
vector<int>::iterator iter = vec.begin();
int previous = *iter;
++iter;
for (; iter != vec.end();)
{
if(*iter == previous)
{
iter = vec.erase(iter);
}
else
{
previous = *iter;
++iter;
}
}
for(iter = vec.begin(); iter != vec.end(); ++iter)
{
cout << *iter << endl;
}
return 0;
}
转自Q?a >http://blog.csdn.net/heyutao007/article/details/6937236
]]>
]]>