我正面临一个奇怪的问题,即在迭代它时擦除STL列表中的元素。我知道擦除元素会使迭代器无效。所以,要么
"testQueue.erase(it++);"
或"it = testQueue.erase(it);"
应该使用。
为了简化我的问题,我尝试在迭代列表时删除所有元素。但是,当使用前一种机制时,我会收到Segfault。
以下是完整代码供您参考。
#include <iostream>
#include <queue>
#include <string>
int main()
{
std::string d1 = "d1";
std::string d2 = "d2";
std::string d3 = "d3";
std::deque<std::string> testQueue;
testQueue.push_back(d1);
testQueue.push_back(d2);
testQueue.push_back(d3);
std::deque<std::string>::iterator it = testQueue.begin();
for(; it!=testQueue.end(); ++it){
std::cout << (*it) << std::endl;
}
std::cout << "========" << std::endl;
it = testQueue.begin();
while(it!=testQueue.end()){
testQueue.erase(it++); // This causes Segfault
//it = testQueue.erase(it); // This one works just fine.
}
std::cout << "========" << std::endl;
std::cout << "========" << std::endl;
std::cout << "========" << std::endl;
std::cout << "========" << std::endl;
std::cout << "========" << std::endl;
it = testQueue.begin();
for(; it!=testQueue.end(); ++it){
std::cout << (*it) << std::endl;
}
return 0;
}
我对后增量方法不起作用的原因一无所知。请注意,最终目标不是使用此方法来擦除所有元素。但是,我想了解我提到的两种方法的区别。
答案 0 :(得分:5)
迭代器失效规则对于不同的容器是不同的。
std::deque::erase
:
所有迭代器和引用都是无效的,除非擦除的成员位于双端队列的末尾(前面或后面)(在这种情况下,只有迭代器和对擦除成员的引用无效)[23.2 .1.3 / 4]
您从testQueue.erase(it++)
收到段错误,因为it++
生成的迭代器也已失效。
答案 1 :(得分:1)
因为迭代器(以及该问题的所有引用)从std::deque
变为无效after erasing元素。你应该使用:
while(it!=testQueue.end()){
it = testQueue.erase(it);
}
答案 2 :(得分:1)
std::deque::erase
擦除迭代器指向的元素,并返回一个指向删除后的元素的迭代器。它也使给定的迭代器无效,因此您只需将其指定为“继续”。
这就是为什么这样做的原因:
while(it!=testQueue.end()){
it = testQueue.erase(it);
}
但是如果你对迭代器进行后递增并将其传递给erase,那么元素将被删除,之后(旧)迭代器被复制并递增。由于旧的迭代器变得无效,增量的迭代器也是如此。
要清除整个双端队列(您似乎想要这样做),还有clear()
答案 3 :(得分:1)
既然你总是只是擦除第一个元素,为什么不让生活变得更简单:
while (!your_list.empty())
your_list.erase(your_list.begin());
答案 4 :(得分:0)
testQueue.erase(it++);
这等于这个
testQueue.erase(it);
it++;
但“它”指向什么都没有,因为它被删除而且无法增加。