C++ 使用迭代器从STL multiset中删除元素
我在一个单独的数据结构中维护多集容器的一组迭代器。过了一会儿,我从这个数据结构中选择了一个迭代器,然后从multiset中删除该迭代器的相关元素。我先用这样的东西:C++ 使用迭代器从STL multiset中删除元素,c++,data-structures,stl,multiset,C++,Data Structures,Stl,Multiset,我在一个单独的数据结构中维护多集容器的一组迭代器。过了一会儿,我从这个数据结构中选择了一个迭代器,然后从multiset中删除该迭代器的相关元素。我先用这样的东西: #include <iostream> #include <set> int main () { std::multiset<int> myints; std::cout << "0. size: " << myints.size() << '\n';
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<10; i++) myints.insert(i);
std::cout << "1. size: " << myints.size() << '\n';
myints.insert (5);
std::cout << "2. size: " << myints.size() << '\n';
std::multiset<int>::iterator it = myints.find(5);
myints.erase (it);
std::cout << "3. size: " << myints.size() << '\n';
myints.erase (it);
std::cout << "4. size: " << myints.size() << '\n';
return 0;
}
erase(it)
使迭代器it
无效,即在erase
之后,迭代器无效,对其执行任何操作都会导致未定义的行为。(当它指向的元素被擦除时,您可能希望它“移动到下一个元素”,但它不是这样做的。)
你的第二种方法不能解决这个问题。它可能是偶然工作的,但在擦除它之后,您仍然在重用它
编辑:根据您的描述“我只想从multiset中擦除一个5,并在擦除后保持其有效,以便下次擦除”。您可以通过创建迭代器的副本,增加原始值,然后通过副本擦除来实现这一点:
it = myints.find(5);
// better add a check here to make sure there actually is a 5 ...
std::multiset<int>::iterator newit = it;
it++;
myints.erase(newit);
it=myints.find(5);
//最好在这里添加一个检查,以确保实际上有一个5。。。
std::multiset::iterator newit=it;
it++;
myints.erase(newit);
由于您已经将它递增,它仍然有效,因为它不指向被擦除所杀死的元素
然而,老实说,我无法想象在什么情况下,这可能是有用的,或者说是必需的。在您的第一种方法中,当您删除迭代器指向的元素时,迭代器将失效,稍后当您尝试再次使用同一迭代器擦除时,您将出现分段错误。
在您的第二种方法中,因为每次执行find after erase时,它都会为您提供正确的迭代器 您可以通过在代码中进行以下更改来修复第一种情况。后增量操作符将返回一个新对象,并将迭代器移动到下一个位置。我还建议在擦除之前做一个结束检查,否则会得到未定义的行为
std::multiset<int>::iterator it = myints.find(5);
if(it != myints.end())
myints.erase (it++);
std::cout << "3. size: " << myints.size() << '\n';
if(it != myints.end())
myints.erase (it++);
std::cout << "4. size: " << myints.size() << '\n';
std::multiset::iterator it=myints.find(5);
if(it!=myints.end())
myints.erase(it++);
这两种方法都有错误吗?你能更清楚地解释一下你到底想做什么吗?我用multiset容器构建了一个排序列表。因此,我需要删除排序列表中间的一些元素,而不知道它们的键。例如,1 2 3 4的排序列表。过了一会儿,我需要从排序列表中删除一个元素(比如中间的元素),而不知道它的键。因此,我维护一组迭代器,指向单独数据结构中排序列表的每个元素,稍后,我将选择一个迭代器并从排序列表中删除相关元素。是的,但您需要删除哪些元素?删除元素的条件是什么?如果您不知道键,如何删除元素?在任何插入或擦除操作之后,位于外部数据结构中的任何迭代器都可能无效。你不能这样做。有没有办法在擦除(它)后保持它的活动状态(指向具有相同键的下一个元素)?可能没有具有“相同键”的下一个元素(我猜你只是指等效的下一个元素-这是一个多集,而不是多映射)。你到底想做什么?从multiset中删除所有5个?我只想从multiset中删除一个5,并在删除后保持它的有效性,以便下次删除。@ARH对什么有效?您刚刚删除了它所指的元素。@jmucchiello给出了关于我答案的第一条评论,我认为他的意思是“在删除的元素之后直接指向该元素”,尽管我质疑这对于像多集
这样的排序结构的实用性。
std::multiset<int>::iterator it = myints.find(5);
if(it != myints.end())
myints.erase (it++);
std::cout << "3. size: " << myints.size() << '\n';
if(it != myints.end())
myints.erase (it++);
std::cout << "4. size: " << myints.size() << '\n';