使用迭代器删除对象类型的向量元素C++

问题描述:

我正在尝试编写一个函数,该函数从listAccounts中删除向量元素,具体取决于该向量元素的account_name。我写了这个:使用迭代器删除对象类型的向量元素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-loop在第一次擦除后变为无效。 if语句中需要'bre​​ak'。 –

+1

@Vlad来自莫斯科只有一个元素的矢量,其中account.name等于名称。 –

一旦你擦除了迭代器所指向的元素,那个迭代器将变得无效。 (对于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); 
    } 
} 

如果你要只有一个元素去掉,然后你可以写

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

迭代器失效。所以你可能不会增加它。

如果容器被修改,迭代器将变为无效。 有两个很好的解决方案:

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

在第二种解决方案中,您可以在矢量上调用'remove'。我认为你的意思是“擦除”。 – navyblue

+0

是的你是对的,修好了。 –