C++迭代vector时通过指针/引用安全删除元素及代码优化
问题说明
现有表示游戏角色buff的CharacterBuff结构体和消耗回合数的pass_phase函数,需要遍历std::vector<CharacterBuff>,对每个元素调用pass_phase,当函数返回true(buff回合结束)时安全删除该元素。同时需要对现有代码的问题点评和更优实现方案。
现有代码的问题点评
- C++里没必要用
typedef struct,直接定义struct CharacterBuff就能直接使用,多写typedef属于冗余的C风格写法。 pass_phase用指针做参数完全没必要:vector里的元素都是合法存在的,不会有空指针情况,用引用参数更安全,还能省去空指针检查的代码。- 新手手动遍历vector删除元素时容易踩坑:比如用索引遍历删除后,后续元素前移,索引++会跳过下一个元素;或者用迭代器遍历直接erase后不处理返回值,导致迭代器失效,触发未定义行为。
更优实现方案
方案1:erase-remove惯用法(推荐)
这是C++删除容器中符合条件元素的标准高效写法,利用标准库算法把要删的元素移到末尾,再一次性删除,避免多次移动元素的开销。
先调整pass_phase为引用版本,再结合算法处理:
#include <vector> #include <algorithm> // 简化struct定义,去掉冗余typedef struct CharacterBuff { BuffTypeEnum buff_type; int value; // < 0 为debuff,> 0 为buff int phases; // < 0 表示无限持续 }; // 改用引用参数,更符合C++风格,无需空指针检查 bool pass_phase(CharacterBuff& buff) { if (buff.phases < 0) { return false; } --buff.phases; return buff.phases <= 0; } void update_buffs(std::vector<CharacterBuff>& buffs) { // erase-remove组合:先把要保留的元素移到前面,再删除末尾的待删元素 buffs.erase( std::remove_if(buffs.begin(), buffs.end(), [](CharacterBuff& buff) { return pass_phase(buff); }), buffs.end() ); }
方案2:迭代器手动遍历(适合小体量vector)
如果不想用标准库算法,手动用迭代器遍历要注意:erase会返回下一个有效迭代器,不能直接++迭代器,要把erase的返回值赋值给迭代器,避免失效。
void update_buffs(std::vector<CharacterBuff>& buffs) { auto it = buffs.begin(); while (it != buffs.end()) { if (pass_phase(*it)) { // erase返回下一个有效迭代器,直接赋值给it即可 it = buffs.erase(it); } else { ++it; } } }
额外优化建议
- 可以把
pass_phase改成CharacterBuff的成员函数,更贴合面向对象设计,调用起来更直观:
struct CharacterBuff { BuffTypeEnum buff_type; int value; // < 0 为debuff,> 0 为buff int phases; // < 0 表示无限持续 bool pass_phase() { if (phases < 0) { return false; } --phases; return phases <= 0; } };
这样处理时直接写it->pass_phase()就行。
- 给成员变量加更明确的注释,比如
phases可以注释成“剩余持续回合数,小于0表示永久生效”,增强代码可读性。
内容的提问来源于stack exchange,提问作者Apoqlite
相关产品推荐
相关产品推荐

