我使用迭代器来移除物品,我想在每一步中擦除地图中的第一项和第二项。
这是代码(此代码是霍夫曼代码的一部分)
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;
}
当迭代器删除第一个项目时,它无法访问要删除的第二个项目,如何删除这两个项目?
答案 0 :(得分:4)
second=++first;
在这里,您不仅要将迭代器分配给second
的第二个元素,而且还要在first
中使用迭代器,因为++
是增量运算符,它递增操作数。似乎没有multimap
迭代器的加法运算符。因此,在再次分配second
之后,您必须减少迭代器:
second = (++first)++;
这将首先递增first
并将其返回second
,之后它将再次递增。或者分配给second
并在之后递增:
second = first;
second++;
或更短:
(second = first)++;
无论如何,您应首先检查容器中是否至少有两个元素。如果没有元素,那么您将尝试递增first == floattnode.end()
,调用未定义的行为。 (我的设置实际上给了我一个无限循环来尝试这个,另见Strange behavior with std::map::iterator's 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
,根据此处的答案Iterator invalidation rules调用erase
,似乎只有被删除的迭代器无效。在这种情况下,你可以使用原始代码。
因为您只检查容器大小是否大于零,所以如果大小正好是1
并且您尝试擦除第二个元素(即floattnode.end()
,则指向未定义的行为,指向在最后一个元素后面。)
second = ++first;
与开头时的错误相同。
答案 1 :(得分:0)
我从不修改集合,列表或地图。我总是创建一个新的并循环旧的,将我想要的条目添加到新的条目中,省略我要删除的条目。
我尝试了解删除到位和迭代器的情况,并认为这对我来说太难了,而且任何人都跟着我。