【问题标题】:Using set::begin() iterator after insertion插入后使用 set::begin() 迭代器
【发布时间】:2012-11-16 21:32:22
【问题描述】:

考虑以下代码:

std::set<int> s;
auto it = s.begin();
s.insert(1);
s.insert(2);
std::cout << *it << std::endl;

输出(至少对我而言)是2。这里发生了什么事?当我取消引用 it 时,它的状态是什么?

我知道当我在一个空集上调用begin() 时,我得到一个等效于end() 的迭代器。我也知道在set 上调用insert 不会使其迭代器无效。即使我现在已经将元素插入到 set 中,迭代器是否以某种方式保持等同于 end() ,所以现在我得到了未定义的行为?这是标准定义的吗?

【问题讨论】:

  • 我相信如果您更改容器,迭代器就会失效。所以这是UB。
  • @ahenderson 不正确,您可能正在考虑向量。
  • 根据this,迭代器没有失效。
  • @Xymotech:这实际上是一个极端案例。该标准仅保证引用容器中元素的迭代器不会失效。情况并非如此,因为当调用 begin() 函数时容器是空的,因此迭代器确实 not 引用容器中的元素。标准中没有关于容器的 end() 迭代器的保证。
  • @JamesMcNellis:在与 Alisdair 重新讨论后,他的立场是措辞不够精确,但没有保证。特别是 end() 迭代器在插入时可能无效的极端情况是在一些实现中,这些实现具有动态分配的哨兵,第一个元素插入到容器中。在这些实现中,在空容器上end() 是一个带有空指针的迭代器,但在第一次插入之后end() 是一个带有指向哨兵对象的指针的迭代器。

标签: c++ iterator set containers


【解决方案1】:

当你在这里调用s.begin() 时,它会返回一个结束迭代器,因为容器是空的。此迭代器不会因插入而失效:每次插入后,此迭代器仍是结束迭代器。

取消引用此迭代器会导致您的程序表现出未定义的行为(无法取消引用结束迭代器)。

【讨论】:

  • 我完全没有将迭代器没有失效的事实应用于结束迭代器。我想“好吧,我正在插入东西,那么如何保证最终迭代器不会改变?”嗯,它没有失效!谢谢
  • 迭代器保证是插入后的end迭代器。标准中的保证仅适用于指向容器中的元素的指针、引用和迭代器。 end() 没有引用容器中的任何元素,因此没有这样的保证。
  • @DavidRodríguez-dribeas:引用自hereThe language specification doesn't state it explicitly. However, there's simply no valid operation on the list that would invalidate the end iterator or associate its value with some other location.(答案是std::list,但std::set 也应该如此。)
  • @DavidRodríguez-dribeas:规范没有说“迭代器进入容器中的元素”,而是说“迭代器进入容器”。结束迭代器引用容器,即使它不引用容器中的元素。
  • @JamesMcNellis:请参阅问题中的 cmets。 end() 不是容器的迭代器,它是超出容器的迭代器。
【解决方案2】:

迭代器it 仍然等于s.end()。取消引用结束迭代器是未定义的行为。这就是你所看到的。试试这个例子

if (it == s.end())
{
    cout << "at end\n";
}

这是合法的代码。

【讨论】:

    【解决方案3】:
    第一种情况下的

    "it" 指向 s.end(),它是 fantom 元素的地址。 fantom 元素的地址只不过是容器中最后一个元素之后的“不存在”元素的地址。一旦 set 被修改,在插入之前最初指向 s.end() 的 "it" 可能与插入之后的 s.end() 不同。

    因此,取消引用“it”会导致未定义的行为。

    【讨论】:

      猜你喜欢
      • 2012-09-13
      • 1970-01-01
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 2019-01-06
      相关资源
      最近更新 更多