【问题标题】:Iterating over a tree while removing and reinserting an element在删除和重新插入元素时遍历树
【发布时间】:2015-11-30 18:57:48
【问题描述】:

看看这段代码摘录:

while( *it <= *it_end and it != myset.end() )
    if(foo(*it++))
        return true;

itit_end 是 std::set(RB 树)的有效迭代器。

foo 将:

  • 删除it,再插入一个与*it值相同的元素,返回false;
  • 删除it 并返回true。

我的问题:

运行这个循环是否安全?

在调用 foo 之前,it 将是树的下一个元素的有效迭代器,但是我担心 std::set 内部的一些内在魔法会使该迭代器无效,例如自平衡算法RB树。

【问题讨论】:

    标签: c++ tree red-black-tree


    【解决方案1】:

    这似乎是安全的,因为您使用的是 std::set

    http://www.cplusplus.com/reference/set/set/erase

    迭代器有效性:

    引用被函数删除的元素的迭代器、指针和引用无效。所有其他迭代器、指针和引用保持其有效性。

    增量将在调用 foo() 之前发生,即在元素被删除之前。换句话说,增量是在迭代器有效时完成的,因此它是安全的。注意 - foo() 仍然使用迭代器在增量之前的值调用。

    增量发生在之前的事实来自于此:

    引用 [C++ 标准][1] 1.9.16(摘自以下链接):

    调用函数时(无论是 不是函数是内联的),每个 价值计算和副作用 与任何论点相关联 表达式,或带有后缀 指定被调用者的表达 函数,先排序 执行每个表达式或 被调用者正文中的声明 功能。 (注:价值计算 和相关的副作用 不同的参数表达式是 未排序。)

    更多内容可以在这里找到:Is it legal to use the increment operator in a C++ function call?

    【讨论】:

    • 有趣的是,您的答案是完全错误的,因为您混淆了后增量和前增量之间的区别。 it 在调用 foo 之前递增。但是,您粘贴的摘录实际上确实回答了“是的,它是安全的”这个问题。我想我应该接受你的回答并投反对票,呵呵。
    • @Kira - 是的,我的第一个答案是错误的。不是由于前/后增量的混淆,而是由于增量是在执行 foo 之前还是之后完成的混淆。答案已更新。
    猜你喜欢
    • 2013-06-23
    • 2010-11-24
    • 2020-10-20
    • 1970-01-01
    • 2017-09-22
    • 2013-08-05
    • 2011-01-02
    • 1970-01-01
    • 2013-07-22
    相关资源
    最近更新 更多