如何在一个步骤中从multimap中删除多个项目

how remove multiple items from multimap in one step of while?

本文关键字:multimap 删除 项目 一个      更新时间:2023-10-16

我使用迭代器来删除项目,我想在while的每一步中从映射中删除第一个项目和第二个项目。

这是代码(此代码是霍夫曼代码的一部分)

std::multimap<float, node *> ::iterator first, second;
first = floattnode.begin();
second = ++first;
while (floattnode.size() != 0) { //floattnode is a multimap mapping frequency to node
root = new node((*first).first + (*second).first, '-');
root->left = new node(((*first).second), 0);
root->right = new node(((*second).second), 1);
floattnode.erase(first);
floattnode.erase(second);//here i have problem
first = floattnode.begin(); //check
floattnode.insert(std::pair<float, node *>(root->freq, root));
first = floattnode.begin();
second = ++first;
}

当迭代器删除它无法访问的第一个项到要删除的第二个项时,我如何删除这两个项?

second=++first;

在这里,您不仅要将迭代器分配给second的第二个元素,而且还要在first中逐步执行迭代器,因为++是递增运算符,它递增其操作数。multimap迭代器似乎没有加法运算符。因此,在再次分配second之后,您将不得不减少迭代器:

second = (++first)++;

这将首先递增first并将其返回到second,之后将再次递增。或者分配给second,然后递增:

second = first;
second++;

或更短:

(second = first)++;

无论如何,您应该首先检查容器中是否至少有两个元素。如果没有元素,那么first == floattnode.end(),您将尝试递增它,调用未定义的行为。(我的设置实际上给了我一个无限循环来尝试这个,另请参阅std::map::迭代器的postincrement的奇怪行为)

while (floattnode.size() != 0) {

您在每个循环回合中创建具有new的新对象,并将它们的指针分配给root,然后将指向它们的指针插入floattnode,但在后面的一个循环回合中再次擦除它们。因此,您在某个时刻丢失了对已创建对象的所有引用。由于您也从未在它们上调用delete,因此您正在泄漏那里的内存。

由于在每次循环运行结束时都会向floattnode添加一个元素,因此在循环条件检查时,floattnode.size()永远不能为零。这是一个无限循环。

root=new node((*first).first+(*second).first,'-');

如果floattnode.size() == 1,则执行此操作,并且second将被取消引用,尽管它指向映射的最后一个元素之后。这会导致未定义的行为。

为了可读性,应该使用first->first而不是(*first).first。(它也这么做)。

floattnode.erase(first);
floattnode.erase(second);//here i have problem

由于我在开头提到的错误,您试图两次擦除同一迭代器。通常,如果容器被修改,容器的迭代器可能会变得无效,所以如果你想确保这不会影响你使用:

floattnode.erase(floattnode.begin());
floattnode.erase(floattnode.begin()); // Notice this is now the originally second element because the first one was erased.

然而,对于multimap,似乎只有擦除的迭代器通过调用erase而无效,这是基于这里的答案:迭代器无效规则。因此,在这种情况下,您应该可以使用原始代码。

因为您只检查容器大小是否大于零,所以如果大小正好是1,并且您试图擦除第二个元素(即floattnode.end(),指向最后一个元素后面),则会再次出现未定义的行为。

second = ++first;

与开头的错误相同。

我从不修改集合、列表或映射。我总是创建一个新的条目,并循环浏览旧的条目,将我想要的条目添加到新的条目中,并省略我想要删除的条目。

我试着理解删除到位和迭代器发生了什么,并认为这对我和任何人来说都太难了。