【问题标题】:C++ value initialized vector iterator comparisonC++值初始化向量迭代器比较
【发布时间】:2020-09-27 16:01:32
【问题描述】:

以下代码在c++17中合法吗?

std::vector<int> x{1,2,3};
std::vector<int>::iterator it{};
bool result = x.begin() != it;

以下引自https://en.cppreference.com/w/cpp/named_req/ForwardIterator

对相同底层序列的所有迭代器和值初始化迭代器定义相等和不等比较

如果我理解正确,比较应该没问题。它似乎适用于 clang 和 gcc,但是当我在调试模式下使用 MSVC 2019 运行它时,我得到一个断言说“向量迭代器不兼容”。

我不是在询问比较的结果,我只对 MSVC 是否符合此处的标准感兴趣。

godbolt 上的实时示例

【问题讨论】:

  • 忽略它。 MSVC 试图帮助您避免在调试模式下出错。如果您在发布模式下编译,它不应该出现。
  • @NathanOliver 我不相信这是真的。我认为,您和 OP 误解了(诚然措辞不佳的)cppreference 文本。而且,如果是这样,调试中的断言会令人担忧,因为这表明库 impl 会在发布时将其视为“UB”。
  • @AsteroidsWithWings 我个人很喜欢它的存在。将迭代器与向量进行比较,将迭代器与向量进行比较有什么意义?即使标准说没关系,因为空向量和空迭代器将“指向”同一事物(无),但这样做没有意义。
  • @NathanOliver 没错,这就是为什么标准 说没关系 ;) VS 不(不应该)断言有效代码只是为了警告你风格;它断言警告您您违反了一些没有提供实际诊断的标准规则

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


【解决方案1】:

MSVC 符合要求。

通常只有相同序列的迭代器可以相互比较。值初始化的迭代器被认为是相同空序列的迭代器。该“虚拟”空序列不同于任何其他序列,并且未(必须)定义跨单独序列的比较,因此该示例可能未定义。

标准报价(最新草案)

[forward.iterators] 前向迭代器的 == 域是相同底层序列上的迭代器的域。 然而,值初始化的迭代器可以被比较并且应该与相同类型的其他值初始化的迭代器进行比较。 [注意:值初始化的迭代器的行为就像它们引用相同空序列的末尾一样。 ——尾注

向量迭代器不能保证实现比这更广泛的域的比较。如果没有,则行为未定义。您的比较不在此域范围内。

【讨论】:

  • 这是正确的,但您可以添加一个标准参考吗?
  • 我不认为这里有任何“可能不正确”;我认为它说代码有UB。标准没有定义这样的顺序,期间
  • @AsteroidsWithWings 我认为以他们的概念不能保证的方式使用类型是允许编译失败的。因此格式不正确。
  • @AsteroidsWithWings 是正确的。潜在的畸形不是一回事。如果是病态的,必须进行诊断。我相信这只是ub。 ub 可以被诊断出来。
  • @eerorika 我从未听说过。您引用的段落明确定义了== 的域,而OP 的案例不在该域中。因此,UB。编译器接受代码证实了这一点,调试中的断言除外(很像 MSVS 对vector::op[] 的调试模式范围检查)
【解决方案2】:

Visual Studio 是正确的。您正在获得一个断言(仅在调试中!),因为您的代码具有未定义的行为,并且实现会就此向您发出警告。

值初始化的迭代器只能与其他值初始化的迭代器进行比较。这是比较指针或迭代器仅适用于序列或数组的规则的概括(一个值得注意的例外是std::less,它方便地提供了整个内存空间的总排序;这是集合的唯一方法,使用默认比较器,不相关的指针可以工作)。

[forward.iterators] 前向迭代器的 == 域是相同底层序列上的迭代器的域。然而,值初始化的迭代器可以被比较并且应该与相同类型的其他值初始化的迭代器进行比较。 [ 注意: 值初始化的迭代器表现得好像它们指向相同空序列的末尾。 —结束注释]

没有为值初始化的迭代器和序列中某个位置的迭代器之间的排序定义语义。

cppreference 文本在这方面的措辞有点糟糕,尽管同一个页面在语义上确实做得更好,以实现两个单数迭代器之间的成功相等:

值初始化的 LegacyForwardIterator 的行为类似于某个未指定空容器的结束迭代器:它与所有相同类型的值初始化的 LegacyForwardIterator 比较。

同样,您不能将迭代器与不同的容器进行比较,因此我们有自己的规则。

【讨论】:

    猜你喜欢
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多