C++ C++;矢量擦除

C++ C++;矢量擦除,c++,vector,stl,C++,Vector,Stl,问题是,当我运行函数时,它在擦除部分崩溃,我不知道为什么 void Grupa::del() { int size = studenti.size(); for (int i=0; i<size; i++) { if (studenti[i].materia1<5 && studenti[i].materia2<5 && studenti[i].materia3<5) { studenti.e

问题是,当我运行函数时,它在
擦除部分崩溃,我不知道为什么

void Grupa::del() {
    int size = studenti.size();
    for (int i=0; i<size; i++) {
        if (studenti[i].materia1<5 && studenti[i].materia2<5 && studenti[i].materia3<5) {
        studenti.erase(studenti.begin()+i);
        }
    }
}
void Grupa::del(){
int size=studenti.size();

对于(int i=0;i当您擦除一个元素时,向量会变小;但您仍然使用原始大小,并且从末尾开始下降。此外,您不希望在擦除后增加
i
,否则您将在擦除后跳过该元素。因此,您希望类似于:

for (size_t i = 0; 
     i != studenti.size(); // don't hoist out of the loop
     /* don't increment here */) 
{
    if (...) {
        studenti.erase(studenti.begin()+i);
    } else {
        ++i;
    }
}

或者查看“删除”的其他答案成语,这是避免这种容易出错的逻辑的一种好方法,也许更有效。

i
超出了向量的大小。由于
erase
调用,向量的大小变小了,但您会一直到保存的大小为止,如果存在已擦除的项,则保存的大小大于实际大小

这就是为什么
erase
返回一个迭代器,它是已擦除元素旁边的元素的有效迭代器:

for (auto it = studenti.begin(); it != studenti.end();) {
    if (it->materia1<5 && it->materia2<5 && it->materia3<5)
        it = studenti.erase(it);
    else
        ++it;
}
for(auto-it=studenti.begin();it!=studenti.end();){

如果(iT>材料1材料2 3P)>看起来你应该使用STL算法,<代码> STD::ReaveVII/<代码>,而不是这样,它方便地避免了其他回答者已经指出的问题。
studenti.erase(std::remove_if(studenti.cbegin(), studenti.cend(), [](Student const& currentStudent) {
    return currentStudent.materia1<5 && currentStudent.materia2<5 && currentStudent.materia3<5;
}), studenti.cend());
studenti.erase(std::remove_if(studenti.cbegin(),studenti.cend(),[](学生常数和当前学生){

return currentStudent.material1我建议使用.1.Nitpick:从技术上讲,它应该是vector::size\u类型,而不是std::size\u类型。@BillyONeal:
vector::size\u类型
std::size\u t
,因为该向量使用默认的分配器,这定义了它。如果您想说明非标准分配器的可能性,然后您需要
分配器::size\u type
decltype(studenti.size())
@Andrew:No,这将给出
int
来匹配整数文本。@Mike:这就是为什么它是一个优步挑剔:)@MikeSeymour:您能解释一下原因吗?我想auto将被实际的基本类型
students.size()
替换,OP可能需要
cbegin
cend