【问题标题】:Invalidated iterator in a vector向量中的无效迭代器
【发布时间】:2017-04-19 16:43:17
【问题描述】:

我知道擦​​除将使迭代器在擦除点和之后失效。考虑:

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 是奇异值,则从最上面的答案看来,这是 UB。但从What is singular and non-singular values in the context of STL iterators? 看来,it 似乎(或曾经)与容器相关联,因此使it 非单数。

感谢您对此进行进一步分析。

【问题讨论】:

    标签: c++ vector iterator language-lawyer undefined-behavior


    【解决方案1】:

    一旦你的迭代器失效,它甚至可能是 UB 将它与其他东西进行比较:

    [C++14: 24.2.1/10]:一个无效迭代器是一个可能是单数的迭代器。

    [C++14: 24.2.1/5]: [..] 大多数表达式的结果对于奇异值是未定义的;唯一的例外是销毁包含奇异值的迭代器,将非奇异值分配给包含奇异值的迭代器,并且对于满足DefaultConstructible 要求的迭代器,使用值初始化的迭代器作为复制或移动操作的来源。 [..]

    请注意,这意味着您也无法将默认构造的迭代器与任何 .end() 进行比较。

    与“指针只是内存地址”的普遍看法相反,这些规则在很大程度上也适用于指针。事实上,迭代器的规则是指针规则的概括。

    【讨论】:

    • 感谢您的回答,我同意您所说的一切。但是,在这种特殊情况下,it 看起来可能是非单数。见stackoverflow.com/questions/5441893/…。虽然it 无效,但它与容器“关联”(更准确地说,被关联),这使得它不是单一的。
    • @PoweredByRice:我在该页面上没有看到任何相关和/或权威的声明。你自己说过:被关联,过去时是关键。它不再关联。
    • 所以我想问题是:无效的迭代器何时是非单数的?
    • @PoweredByRice:我不确定。我目前的解释是,这归结为迭代器失效和实际上“物理”破坏迭代器之间的区别。也就是说,例如,迭代器在重新散列发生后失效,即使容器的结果状态可能与之前相同。我认为该标准希望我们考虑所有可能是单一的无效迭代器并在此基础上继续。
    【解决方案2】:

    形式上,任何指向被擦除元素上或之后的元素的迭代器都无效。所以

    1. 是的,这是 UB(尽管它是引擎盖下的指针。)

    2. 又是 UB,尽管有明显的合理性。

    【讨论】:

    • 一些 C++ 库对向量迭代器使用类类型(这会导致由于 ADL 导致库中相同代码的行为不同,例如 find(v.begin(), v.end(), x);)。在调试模式下,他们尝试诊断,例如,将迭代器与不同向量进行比较
    猜你喜欢
    • 2015-07-31
    • 2014-10-23
    • 2011-04-22
    • 2012-06-16
    • 1970-01-01
    • 2017-08-29
    • 2011-11-15
    相关资源
    最近更新 更多