简体   繁体   English

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

[英]Removing a vector element of object type using an iterator c++

I am trying to write a function that removes a vector element from listAccounts depending on the account_name of that vector element. 我正在尝试编写一个函数,该函数根据该矢量元素的account_name从listAccounts中删除该矢量元素。 I have written this: 我写了这个:

void Account::remove_account(string name) {

    auto iter = listAccounts.begin();

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

}

But I am getting a Segmentation fault from the vector removal, from what I understand it means that I tried to access memory that I do not have access to, but i'm not sure how to correctly write this. 但是从向量移除中我遇到了分段错误,据我了解,这意味着我试图访问我无权访问的内存,但是我不确定如何正确地编写它。

Once you erase the element pointed to by an iterator, that iterator becomes invalid. 擦除迭代器指向的元素后,该迭代器将无效。 (for a std::vector , all other iterators after the erased element becomes invalid too). (对于std::vector ,被删除元素之后的所有其他迭代器也将无效)。 And incrementing or dereferencing an invalid iterator has undefined behavior. 并且递增取消引用无效的迭代器具有未定义的行为。

You could do (assuming only one element is to be removed): 您可以这样做(假设只删除一个元素):

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

For multiple elements, that will be: 对于多个元素,将是:

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

If container is modified iterator becomes invalid. 如果修改了容器,则迭代器无效。 There are two good solutions: 有两个好的解决方案:

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

If you are going to remove just one element then you can write 如果您只删除一个元素,则可以编写

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

As for your code then after this statement 至于你的代码然后在此声明之后

listAccounts.erase(iter);

the iterator becomes invalid. 迭代器无效。 So you may not increment it. 因此,您可能无法增加它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM