【问题标题】:What is singular and non-singular values in the context of STL iterators?在 STL 迭代器的上下文中,什么是奇异值和非奇异值?
【发布时间】:2011-07-23 10:47:42
【问题描述】:

C++ 标准 (2003) 的第 24.1/5 节内容如下:

就像一个指向数组的常规指针 保证有一个指针 指向最后一个元素的值 数组的,所以对于任何迭代器类型 有一个迭代器值指向 过去 a 的最后一个元素 对应的容器。这些值 被称为过去的值。价值观 迭代器 i 的 表达式 *i 被定义被调用 可取消引用。图书馆从不 假设过去的值是 可取消引用。 迭代器也可以 具有不存在的奇异值 与任何容器相关联。 [示例:在声明一个 未初始化的指针 x(与 int* 一样) x;), x 必须总是假设有 一个指针的奇异值。] 大多数表达式的结果是 奇异值未定义;这 唯一的例外是分配 a 迭代器的非奇异值 持有奇异值。在这种情况下 奇异值被覆盖 与任何其他值相同。 可取消引用的值总是 非单数。

我无法真正理解 粗体 中显示的文字?

  • 什么是奇异值和非奇异值?它们是如何定义的?在哪里?
  • 如何以及为什么可取消引用的值总是非奇异的?

【问题讨论】:

    标签: c++ pointers stl iterator standards


    【解决方案1】:

    如果我理解正确的话,迭代器的奇异值本质上等同于未分配的指针。它是一个迭代器,它没有被初始化为指向任何地方,因此没有它正在迭代的明确定义的元素。例如,声明一个未设置为指向范围元素的新迭代器会将该迭代器创建为单个迭代器。

    正如规范的一部分所暗示的那样,单数迭代器是不安全的,并且不能对它们使用任何标准迭代器操作,例如递增、赋值等。您所能做的就是为它们分配一个新值,希望将它们指向有效数据。

    我认为有这个定义的原因是这样的陈述

    set<int>::iterator itr;
    

    可以在规范允许的同时具有标准化的含义。这里的“奇异”一词可能是指奇异点的数学定义,在不太正式的设置中也称为“不连续性”。

    【讨论】:

    • 可以将默认构造的istream_iterator 视为单数吗?
    • 我不这么认为。这是一个有效的结束迭代器。如果它是单数,则不能使用它来定义流的 enf,因为您无法将其与任何其他迭代器进行比较。
    【解决方案2】:

    迭代器也可以有奇异值不与任何容器相关联

    我想这就是它的定义。

    可取消引用的值如何以及为什么总是非奇异的?

    因为如果他们不这样做,取消引用它们将是未定义的行为。

    【讨论】:

      【解决方案3】:

      看看What is an iterator's default value?

      正如引用所指出的,奇异值是不与任何容器关联的迭代器值。奇异值几乎是无用的:你不能推进它,取消引用它等等。获得奇异迭代器的一种方法(唯一的方法?)是不初始化它,如 templatetypedef 的答案所示。

      可以使用奇异迭代器做的一件有用的事情是分配它一个非奇异值。当你这样做时,你可以用它做任何你想做的事情。

      根据定义,非奇异值几乎是迭代器值, 与容器相关联。这就回答了为什么可取消引用的值总是非奇异的:不指向任何容器的迭代器不能被取消引用(这会返回什么元素?)。

      正如 Matthieu M. 正确指出的,非奇异值可能仍然是不可解引用的。一个例子是过去的迭代器(可通过调用 container.end() 获得):它与容器相关联,但仍不能被引用。

      我不能说这些术语是在哪里定义的。然而,谷歌对“定义:单数”(以及其他定义)有这样的说法:

      remarkable: unusual or striking
      

      我想这可以解释术语。

      【讨论】:

      • 当心!非奇异值包括过去的结束迭代器,这个不能被取消引用。
      • @Matthieu:你是 100% 正确的。我已经更新了我的答案以反映非奇异值可能仍然是不可取消引用的。谢谢!
      【解决方案4】:

      什么是奇异值和非奇异值?它们是如何定义的?在哪里?

      让我们使用Iterator 的最简单化身:指针。

      对于指针:

      • 提到的奇异值是NULL 值一个未初始化的值。
      • 一个非奇异值是一个显式初始化的值,它可能仍然不能取消引用(不应取消引用过去的指针)

      我会说NULL 指针是一个奇异值,尽管不是唯一的,因为它表示值的缺失。

      常规迭代器的等价物是什么?

      std::vector&lt;int&gt;::iterator it;,大多数迭代器(链接到容器的)的默认构造函数创建一个奇异值。由于它没有绑定到容器,因此任何形式的导航(递增、递减……)都是没有意义的。

      可解引用的值如何以及为什么总是非奇异的?

      根据定义,奇异值表示没有实际值。它们出现在多种语言中:Python 的None、C# 的null、C 的NULL、C++ 的std::nullptr。问题是在 C 或 C++ 中,它们也可能是简单的垃圾......(无论之前在内存中存在什么)

      默认构造的迭代器是奇异值吗?

      不一定,我猜。标准没有要求,可以想象使用哨兵对象。

      【讨论】:

      • 我的想法和你一样,singular 迭代器指的是空指针或std::istream_iterator&lt;T&gt;(),但后来我重读了几次引用并得出结论,情况可能并非如此。可以保证您不仅可以分配空指针,还可以比较空指针(或std::istream_iterator&lt;T&gt;() 所以我不再相信这种解释成立。
      • @David:我认为这里的标准不清楚。 most of 后跟 the only exception 的使用是可疑的,为什么不使用 all*/*except 呢?似乎他们也愿意考虑统一化的值(如示例),而不仅仅是空值。
      • “所指的奇异值”实际上是不是 NULL。引用的示例文本很清楚:“在声明未初始化的指针 x 之后(与 int* x; 一样),必须始终假定 x 具有指针的奇异值。”。现在,未初始化的指针不是NULL。您甚至无法将其与 NULL 进行比较。
      • @MSalters:它应该被纠正,但我错过了一个/ 来关闭strike 标签:)
      猜你喜欢
      • 2015-12-22
      • 2010-10-06
      • 2012-12-25
      • 2013-02-02
      • 2011-07-01
      • 1970-01-01
      • 2016-09-13
      • 2011-05-12
      • 1970-01-01
      相关资源
      最近更新 更多