2017-10-15 5 views
1

Ich versuche, eine Funktion zu schreiben, die ein Vektorelement aus listAccounts in Abhängigkeit von dem account_name dieses Vektorelements entfernt. Ich habe dies geschrieben:Entfernen eines Vektorelements vom Objekttyp mit einem Iterator C++

void Account::remove_account(string name) { 

    auto iter = listAccounts.begin(); 

    for (; iter != listAccounts.end(); iter++) { 
     if ((*iter).account_name == name) { 
      listAccounts.erase(iter); 
     } 
    } 

} 

Aber ich einen Segmentation fault aus der Vektor Entfernung bekommen, von dem, was ich verstehe, es bedeutet, dass ich versuchte, auf Speicher zuzugreifen, die ich habe keinen Zugang zu, aber ich bin nicht sicher, wie man das richtig schreibt.

+1

Möchten Sie nur ein Element oder alle Elemente mit dem angegebenen Wert entfernen? –

+0

Das Duplikat erklärt, dass Ihre For-Schleife nach dem ersten Löschen ungültig wird. Du brauchst einen 'break; 'in der if-Anweisung. –

+1

@Vlad aus Moskau Nur ein Element in dem Vektor, der account.name gleich name hat. –

Antwort

2

Sobald Sie das Element löschen, auf das ein Iterator zeigt, wird dieser Iterator ungültig. (für eine std::vector, alle anderen Iteratoren nach dem gelöschten Element wird auch ungültig). Und inkrementieren oder Dereferenzierung ein ungültiger Iterator hat undefiniertes Verhalten.

Sie tun könnte (vorausgesetzt, nur ein Element entfernt werden):

void Account::remove_account(string name) { 
    auto iter = std::find_if(listAccounts.begin(), listAccounts.end(), 
       [&](const auto& s){ return s.account_name == name; }); 
    if(iter != listAccounts.end()) 
     listAccounts.erase(iter); 
} 

Für mehrere Elemente, das sein wird:

void Account::remove_account(string name) { 
    for(auto iter = listAccounts.begin(); iter != listAccounts.end();){ 
     iter = std::find_if(iter, listAccounts.end(), 
        [&](const auto& s){ return s.account_name == name; }); 
     if(iter != listAccounts.end()) 
      iter = listAccounts.erase(iter); 
    } 
} 
0

Wenn Sie nur ein Element zu entfernen, werden dann Sie können

bool Account::remove_account(std::string &name) 
{ 
    auto it = std::find_if(listAccounts.begin(), 
          listAccounts.end(), 
          [&](const auto &item) 
          { 
           return item.account_name == name; 
          }); 

    bool success = it != listAccounts.end(); 

    if (success) listAccounts.erase(it); 

    return success; 
} 

Wie für Ihren Code dann nach dieser Aussage

0 schreiben
listAccounts.erase(iter); 

der Iterator wird ungültig. Sie dürfen es also nicht erhöhen.

2

Wenn Container geändert wird, wird der Iterator ungültig. Es gibt zwei gute Lösungen:

void Account::remove_account(const string& name) { 
    auto iter = listAccounts.begin(); 

    while iter != listAccounts.end()) { 
     if (iter->account_name == name) { 
      iter = listAccounts.erase(iter); 
     } else { 
      ++iter; 
     } 
    } 
} 

// or 
void Account::remove_account(const string& name) { 
    listAccounts.erase(
     std::remove_if(std::begin(listAccounts), std::end(listAccounts), 
         [&name](const auto& item) { 
          return item.account_name == name; 
         }), 
     std::end(listAccounts)); 
} 
+0

In der zweiten Lösung rufen Sie 'remove' auf dem Vektor. Ich denke, du hast 'Löschen' gemeint. – navyblue

+0

Ja, Sie haben Recht, behoben. –

Verwandte Themen