2017-10-15 16 views
1

そのベクトル要素のaccount_nameに応じてlistAccountsからベクトル要素を削除する関数を記述しようとしています。私は、この書かれている:イテレータを使用してオブジェクト型のベクトル要素を削除するC++

void Account::remove_account(string name) { 

    auto iter = listAccounts.begin(); 

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

} 

しかし、私は、私はそれは私がへのアクセスを持っていないメモリにアクセスしようとしたことを意味を理解するものとはベクトルの除去からセグメンテーションフォールトを取得していますが、しかし、私はよく分かりませんこれを正しく書く方法。

+1

指定された値を持つ要素またはすべての要素を削除しますか? –

+0

重複は、forループが最初の消去後に無効になることを説明します。 if文には 'break;'が必要です。 –

+1

@Vlad from Moscowモスクワの@Vlad名前に等しいaccount.nameを持つベクトル内のただ1つの要素。 –

答えて

2

イテレータが指す要素を消去すると、そのイテレータは無効になります。 (std::vectorの場合、消去された要素の後のすべてのイテレータも無効になります)。そしてをインクリメントするまたは逆参照無効なイテレータには未定義の動作があります。あなたが行うことができ

(一つだけの要素が除去されると仮定した場合):複数の要素については

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); 
} 

、それは次のようになります。

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

あなたはただ一つの要素を削除しようとしている場合書くことができます

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; 
} 

あなたのコードについては、この文の後に

listAccounts.erase(iter); 

イテレータが無効になります。だからあなたはそれを増やせないかもしれない。

2

コンテナが変更された場合、反復子は無効になります。 2つの良い解決策があります:

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

2番目のソリューションでは、ベクター上で 'remove'を呼び出します。私はあなたが '消去 'を意味していると思う。 – navyblue

+0

はい、あなたは正しいです。 –

関連する問題