2017-03-27 2 views
0

J'utilise actuellement un vecteur pour contenir les personnes dans un programme. Je suis en train de le supprimer avecC++ Supprimer un objet dans un vecteur

vectorname.erase(index);

Je passe le vecteur dans une fonction, ainsi que l'élément que je veux supprimer. Mon principal problème est comment puis-je améliorer mon code en termes de vitesse de compilation?

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 

class person { 
    private: 
     string name; 
    public: 
     person() {} 
     person(string n):name(n){} 
     const string GetName() {return name;} 
     void SetName(string a) { name = a; } 
}; 

void DeleteFromVector(vector<person>& listOfPeople,person target) { 
    for (vector<person>::iterator it = listOfPeople.begin();it != listOfPeople.end();++it) {//Error 2-4 
     if (it->GetName() == target.GetName()) { 
      listOfPeople.erase(it); 
      break; 
     } 
    } 
} 

int main(){ 
    //first group of people 
    person player("Player"), assistant("Assistant"), janitor("Janitor"), old_professor("Old Professor"); 

    //init of vector 
    vector<person> listOfPeople = { player, assistant, janitor, old_professor }; 

    DeleteFromVector(listOfPeople, janitor); 
} 
+1

Pourquoi définissez-vous l'itérateur dans 'for', mais ne l'utilisez pas? –

+0

Vous faites tout faux. Vous utilisez 'erase' mais vous ne prenez pas sa valeur de retour en tant que nouvel itérateur, donc après cela, vous utilisez des itérateurs incorrects et corrompus. Et, il y a une bien meilleure façon de le faire que vous pouvez voir ici http://en.cppreference.com/w/cpp/algorithm/remove et https://en.wikipedia.org/wiki/Erase%E2%80 % 93remove_idiom –

+0

OK, je vois votre 'break' immédiatement après avoir utilisé' erase' donc je suppose que vous n'utilisez pas d'itérateurs invalides après tout. –

Répondre

2

Il n'y a pas besoin de définir index, iterator peut être utilisé pour accéder à des objets dans le vecteur:

for (vector<person>::iterator it = listOfPeople.begin(); it != listOfPeople.end(); ++it) {//Error 2-4 
    if (it->GetName() == target.GetName()) { 
     listOfPeople.erase(it); 
     break; 
    } 
} 

Depuis la ligne suivante consiste à briser boucle, nous ne considérons pas itérateur invalide problème ici.

+1

La prochaine ligne est à casser pour la boucle, devrions-nous toujours considérer le problème d'itérateur invalide? –

+0

Ah, cela permettrait d'éviter le problème. –

+0

@MartinZhai Merci pour l'info :) – CraftedGaming

1

Vous n'avez pas besoin de cette boucle pour supprimer l'objet du vecteur. Pourquoi utiliser :

#include <algorithm> 
//... 
void DeleteFromVector(vector<person>& listOfPeople, const person& target) 
{ 
    // find the element 
    auto iter = std::find_if(listOfPeople.begin(), listOfPeople.end(), 
          [&](const person& p){return p.GetName() == target.GetName();}); 

    // if found, erase it 
    if (iter != listOfPeople.end()) 
     listOfPeople.erase(iter); 
} 
+0

Celui-ci est mieux que la réponse acceptée - utilisez le std :: find_if au lieu de faire le travail vous-même. Et s'il y a un opérateur == défini pour la classe de personne, vous pouvez utiliser std :: find() – Tim

+0

@PaulMcKenzie, l'objet "p" dans la ligne de retour et la "cible" provoque des erreurs. Erreur (active) l'objet a des qualificatifs de type incompatibles avec la fonction membre "person :: GetName" Erreur (active) l'objet a des qualificatifs de type incompatibles avec la fonction membre "person :: GetName" Erreur C2662 'std :: string personne :: GetName (void)': ne peut pas convertir 'this' pointeur de 'const person' en 'personne &' – CraftedGaming

+0

@CraftedGaming Ensuite, soit supprimer le 'const' ou make' GetName() 'un fonction const. Mieux vaut en faire une fonction 'const'. – PaulMcKenzie