一个向量中的迭代器无效化了。

4

我知道擦除操作会使得迭代器在擦除点及其之后的位置失效。请考虑以下代码:

std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.end() - 1; //last element
vec.erase(vec.begin()); //shift everything one to the left, 'it' should be the new 'end()' ?
std::cout << (it == vec.end()); //not dereferencing 'it', just comparing, UB ?

比较(而非引用)一个被使无效的迭代器(在这种情况下为it)是否是未定义行为?如果不是,it == vec.end()保证成立吗?
编辑:从顶部的答案看来,如果只有it奇异值,那么这是未定义行为。但是从STL迭代器上下文中的奇异和非奇异值是什么?可以看出,it(或曾经)与容器相关联,因此使it非奇异
我会感激更深入的分析,谢谢。
2个回答

6
一旦您的迭代器被使无效,甚至将其与其他内容进行比较可能会导致未定义行为:
[C++14: 24.2.1/10]: 无效的迭代器是指可能为单值的迭代器。
[C++14: 24.2.1/5]: 对于单值,大多数表达式的结果都是未定义的;唯一的例外是销毁保持单值的迭代器、将非单值赋给保持单值的迭代器以及对于满足DefaultConstructible要求的迭代器,使用值初始化的迭代器作为复制或移动操作的源。[..]
请注意,这意味着您也不能将默认构造的迭代器与任何.end()进行比较。
与“指针只是内存地址”这一普遍观念相反,这些规则在很大程度上也适用于指针。实际上,迭代器的规则是指针规则的概括。

感谢您的回答,我同意您所说的一切。然而,在这种特殊情况下,看起来 it 可能是非单数的。请参见 https://dev59.com/uW035IYBdhLWcg3wZvJg 。虽然 it 是无效的,但它与容器“关联”(更准确地说,曾经关联),这使得它是非单数的。 - PoweredByRice
@PoweredByRice:我在那个页面上没有看到任何相关和/或有权威的陈述。你自己说了:“曾经”被关联,过去式是关键。 它现在不再关联。 - Lightness Races in Orbit
所以我想问题是:何时无效的迭代器是非奇异的? - PoweredByRice
@PoweredByRice:我不确定。我目前的解释是这取决于迭代器失效和实际上“物理”破坏迭代器之间的区别。也就是说,例如,在重新散列发生后,即使容器的结果状态可能与之前相同,迭代器也会失效。我认为标准要求我们考虑所有无效迭代器都有可能是奇异的,并在此基础上继续进行。 - Lightness Races in Orbit

1

正式地说,指向被删除元素或之后元素的任何迭代器都将失效。因此,

  1. 是的,这是未定义行为(尽管在底层它是一个指针)。

  2. 再次是未定义行为,尽管显然很有可能。


1
一些C++库使用类类型来表示向量迭代器(这会导致由于ADL在不同库之间产生相同代码的不同行为,例如find(v.begin(), v.end(), x);)。在调试模式下,它们会尝试诊断,例如,比较不同向量中的迭代器。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接