使用迭代器 C++ 删除对象类型的向量元素
Posted
技术标签:
【中文标题】使用迭代器 C++ 删除对象类型的向量元素【英文标题】:Removing a vector element of object type using an iterator c++ 【发布时间】:2017-10-15 19:54:13 【问题描述】:我正在尝试编写一个函数,根据该向量元素的 account_name 从 listAccounts 中删除一个向量元素。我写了这个:
void Account::remove_account(string name)
auto iter = listAccounts.begin();
for ( ; iter != listAccounts.end(); iter++)
if ((*iter).account_name == name)
listAccounts.erase(iter);
但是我从向量删除中得到了一个分段错误,据我了解,这意味着我试图访问我无权访问的内存,但我不确定如何正确编写它。
【问题讨论】:
您想只删除一个元素还是删除所有具有给定值的元素? 副本说明您的 for 循环在第一次擦除后变得无效。您需要在 if 语句中使用break;
。
@Vlad 来自莫斯科 向量中有一个 account.name 等于 name 的元素。
@Captain Giraffe 我明白了,谢谢。
【参考方案1】:
一旦你删除了一个迭代器指向的元素,那个迭代器就失效了。 (对于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);
【讨论】:
【参考方案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));
【讨论】:
在第二个解决方案中,您在向量上调用remove
。我想你的意思是erase
。【参考方案3】:
如果你只想删除一个元素,那么你可以写
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);
迭代器变得无效。所以你不能增加它。
【讨论】:
以上是关于使用迭代器 C++ 删除对象类型的向量元素的主要内容,如果未能解决你的问题,请参考以下文章