在STL迭代器的上下文中,什么是单数和非奇异值?

时间:2011-03-26 11:07:05

标签: c++ pointers stl iterator standards

C ++标准(2003)第24.1 / 5节中的内容为

  

就像指向数组的常规指针一样   保证有一个指针   指向最后一个元素的值   对于任何迭代器类型,数组都是如此   有一个指向的迭代器值   过去的最后一个元素   相应的容器。这些价值观   被称为过去的价值观。值   一个迭代器我的   表达式* i被定义被调用   提领。图书馆永远不会   假设过去的价值是   提领。 迭代器也可以   具有不是的奇异值   与任何容器相关联。   [例子:宣布之后   未初始化的指针x(与int *一样)   x;),x必须始终假定为   指针的奇异值。]   大多数表达的结果是   未定义的奇异值;该   唯一的例外是a的赋值   迭代器的非奇异值   具有独特的价值。在这种情况下   奇异值被覆盖了   与任何其他价值相同。   始终是可解除引用的值   奇异的。

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

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

4 个答案:

答案 0 :(得分:8)

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

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

我认为有这个定义的原因是像

这样的陈述
set<int>::iterator itr;

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

答案 1 :(得分:8)

  

迭代器也可以具有与任何容器无关的奇异值

我想这是它的定义。

  

可解除引用值的方式和原因总是非奇异的?

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

答案 2 :(得分:2)

查看What is an iterator's default value?

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

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

非奇异值几乎是定义的,与容器关联的 的迭代器值。这就解释了为什么可解除引用的值总是非单数的:不指向任何容器的迭代器不能被解引用(这将返回什么元素?)。

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

我不知道这些术语的定义。但是,谷歌有关于“定义:单数”(以及其他定义)的说法:

remarkable: unusual or striking

我想这可以解释术语。

答案 3 :(得分:2)

  

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

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

指针:

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

我会说NULL指针是一个奇异值,虽然不是唯一的值,因为它代表缺少值。

  

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

std::vector<int>::iterator it;,大多数迭代器(链接到容器的那些)的默认构造函数创建一个奇异值。由于它没有绑定到容器,任何形式的导航(增量,减量......)都没有意义。

  

可解除引用值的方式和原因总是非奇异的?

根据定义,奇异值表示缺少实际值。它们以多种语言出现:Python的None,C#的null,C的NULL,C ++的std::nullptr。问题在于,在C或C ++中,它们也可能是简单的垃圾......(以前在内存中存在的任何东西)

  

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

不一定,我想。标准不要求它,人们可以想象使用哨兵对象。