我正在尝试从对象列表中删除一个元素,如果该对象的一个属性与某个条件匹配。这是我的函数,但是,在执行此操作并打印内容之后,erase()似乎没有任何效果。我在这里做错了什么?
void FileReader::DeleteProcess(int id, list<Process> listToDeleteFrom)
{
list<Process>::iterator process;
for(process = listToDeleteFrom.begin(); process != listToDeleteFrom.end(); process++)
{
if (process -> ID == id)
{
listToDeleteFrom.erase(process);
}
}
}发布于 2012-10-01 10:31:25
首先,您需要通过引用传递列表;您的代码正在处理一个副本,因此它所做的更改不会影响调用者的列表:
void FileReader::DeleteProcess(int id, list<Process> & listToDeleteFrom)
^其次,擦除列表元素会使引用该元素的任何迭代器失效,因此尝试在之后继续迭代将导致未定义的行为。如果只有一个要删除的元素,那么在调用erase之后直接从函数返回;否则,循环需要构造如下:
for (auto it = list.begin(); it != list.end(); /* don't increment here */) {
if (it->ID == id) {
it = list.erase(it);
} else {
++it;
}
}发布于 2012-10-01 10:27:13
当迭代器在list上迭代时调用erase()会使迭代器失效。将要擦除的元素添加到第二个列表中,然后删除它们。
还要注意,您是通过值传递列表的,而不是使用引用或指针。你是想用list<Process>& listToDeleteFrom还是list<Process>* listToDeleteFrom?
发布于 2012-10-01 10:35:13
您看不到所反映的更改的原因是,您的列表不是通过引用传递的,因此您只是从列表的副本中删除元素。
将其更改为:
void FileReader::DeleteProcess(int id, list<Process> &listToDeleteFrom) //note &这将保持函数中的语法不变,并修改原始语法。
但是,删除元素的方式有点不太理想。如果你有C++11,下面的代码将会解决你的失效问题,并且使用为这个任务设计的现有算法,更加得体:
listToDeleteFrom.erase ( //erase matching elements returned from remove_if
std::remove_if(
std::begin(listToDeleteFrom),
std::end(listToDeleteFrom),
[](const Process &p) { //lambda that matches based on id
return p->ID == id;
}
),
std::end(listToDeleteFrom) //to the end of the list
);请注意,其中保留了std::list<>::erase,以便实际擦除匹配的元素。这就是所谓的擦除习惯用法。
https://stackoverflow.com/questions/12666869
复制相似问题