Ошибка сегментации при стирании последнего элемента в векторе

Я пытаюсь стереть последний элемент вектора с помощью итератора. Но я получаю ошибку сегментации при стирании элемента.

Ниже мой код:

    for (vector<AccDetails>::iterator itr = accDetails.begin(); itr != accDetails.end(); ++itr) {
    if (username == itr->username) {
            itr = accDetails.erase(itr);
    }
}

Что-то не так с моей итерацией?


person Joel Seah    schedule 03.08.2013    source источник
comment
возможный дубликат Удалить элементы вектора внутри цикла   -  person Borgleader    schedule 03.08.2013


Ответы (2)


Это хорошее место для применения идиомы удаления/стирания:

accDetails.erase(
    std::remove_if(
        accDetails.begin(), accDetails.end(), 
        [username](AccDetails const &a) { return username == a.username; }),
     accDetails.end());

В качестве бонуса это, вероятно, будет немного быстрее, чем то, что вы делали (или, может быть, немного быстрее, если ваш вектор большой). Стирание каждого элемента по отдельности заканчивается как O(N2), но это будет O(N), что может быть довольно важным, когда/если N становится большим.

Если вы не можете использовать С++ 11, лямбда не будет работать, поэтому вам нужно будет отдельно закодировать это сравнение:

class by_username { 
    std::string u;
public:
    by_username(std::string const &u) : u(u) {}
    bool operator()(AccDetails const &a) { 
        return u == a.username;
    }
};

accDetails.erase(
    std::remove_if(accDetails.begin(), accDetails.end(), by_username(username)), 
    accDetails.end());

В качестве альтернативы вы можете перегрузить operator== для своего класса AccDetails и обработать сравнение там. Например:

#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>

class AccDetail {
    std::string name;
    int other_stuff;
public:
    AccDetail(std::string const &a, int b) : name(a), other_stuff(b) {}

    bool operator==(std::string const &b) {
        return name == b;
    }

    friend std::ostream &operator<<(std::ostream &os, AccDetail const &a) {
        return os << a.name << ", " << a.other_stuff;
    }
};

int main(){
    std::vector<AccDetail> ad = { {"Jerry", 1}, { "Joe", 2 }, { "Bill", 3 } };

    std::cout << "Before Erase:\n";
    std::copy(ad.begin(), ad.end(), std::ostream_iterator<AccDetail>(std::cout, "\n"));
    ad.erase(
        std::remove(ad.begin(), ad.end(), "Joe"),
        ad.end());

    std::cout << "\nAfter Erasing Joe:\n";
    std::copy(ad.begin(), ad.end(), std::ostream_iterator<AccDetail>(std::cout, "\n"));
}
person Jerry Coffin    schedule 03.08.2013
comment
Я получаю сообщение об ошибке ожидаемое первичное выражение в этой строке [username].... Так мне нужно написать оператор () в моей структуре? - person Joel Seah; 03.08.2013

Я изучаю безопасный способ стирания элементов с моего лидера. Сначала найдите все элементы. Во-вторых, сотрите их один за другим.

queue< vector<AccDetails>::iterator > q;
for (vector<AccDetails>::iterator itr = accDetails.begin(); itr != accDetails.end(); ++itr) {
    if (username == itr->username) {
        //itr = accDetails.erase(itr);
        q.push(itr);
    }
}
while(!q.empty()){
    vector<AccDetails>::iterator itr = q.front();
    accDetails.erase(itr);
    q.pop();
}
person alexis    schedule 03.08.2013
comment
@DanielKO, ты не можешь просто скопировать код и запустить. Я просто показываю метод, метод решения такой проблемы. - person alexis; 03.08.2013
comment
Алгоритм неверный. Это не только алгоритм квадратичного времени, все элементы, стертые после первого, неверны. Он может даже получить доступ за пределами последовательности. Попробуйте использовать его, чтобы стереть все четные числа в векторе {1, 2, 3, 4, 5, 6}. - person DanielKO; 05.08.2013
comment
@DanielKO, да, ты прав. Я ошибаюсь в использовании. Что изменится в точках итератора. Тогда это вызовет ошибку. Что-то вроде карты с ключом и значением может использовать мой алгоритм. Если нам нужно услышать что-то, основанное на ценности. Используйте итератор, чтобы найти ключи, затем удалите элементы по ключам - person alexis; 08.08.2013