STL 迭代器中的奇异值和非奇异值是什么?
C++ 标准 (2003) 的第 §24.1/5 节内容如下:
就像指向数组的常规指针一样 保证有一个指针 指向最后一个元素之后的值 数组的,因此对于任何迭代器类型 有一个迭代器值指向 超过 a 的最后一个元素 相应的容器。这些值 被称为过期值。价值观 迭代器 i 的 表达式 *i 被定义并被调用 可取消引用。图书馆从来不 假设期末值为 可取消引用。 迭代器还可以 具有不存在的奇异值 与任何容器关联。 [示例:声明后 未初始化的指针 x (与 int* 一样 x;), x 必须始终被假设为 指针的奇异值。] 大多数表达式的结果是 对于奇异值未定义;这 唯一的例外是a的赋值 迭代器的非奇异值 具有奇异值。在这种情况下 奇异值被覆盖 与任何其他值相同的方式。 可解引用的值始终是 非奇异。
我无法真正理解粗体显示的文本?
- 什么是奇异值和非奇异值?它们是如何定义的?那么在哪里呢?
- 可解引用值如何以及为何总是非奇异?
The section §24.1/5 from the C++ Standard (2003) reads,
Just as a regular pointer to an array
guarantees that there is a pointer
value pointing past the last element
of the array, so for any iterator type
there is an iterator value that points
past the last element of a
corresponding container. These values
are called past-the-end values. Values
of an iterator i for which the
expression *i is defined are called
dereferenceable. The library never
assumes that past-the-end values are
dereferenceable. Iterators can also
have singular values that are not
associated with any container.
[Example: After the declaration of an
uninitialized pointer x (as with int*
x;), x must always be assumed to have
a singular value of a pointer.]
Results of most expressions are
undefined for singular values; the
only exception is an assignment of a
non-singular value to an iterator that
holds a singular value. In this case
the singular value is overwritten the
same way as any other value.
Dereferenceable values are always
nonsingular.
I couldn't really understand the text shown in bold?
- What is singular value and nonsingular value? How are they defined? And where?
- How and why dereferenceable values are always nonsingular?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想这就是它的定义。
因为如果他们不这样做,取消引用它们将是未定义的行为。
I suppose that's its definition.
Because if they wouldn't, dereferencing them would be undefined behavior.
查看迭代器的默认值是什么?。
正如引用所指出的,奇异值是不与任何容器关联的迭代器值。奇异值几乎是无用的:你不能推进它,取消引用它,等等。获得奇异迭代器的一种方法(唯一的方法?)是不初始化它,如 templatetypedef 的答案所示。
使用奇异迭代器可以做的有用的事情之一就是为其分配一个非奇异值。当你这样做时,你可以用它做任何你想做的事情。
根据定义,非奇异值几乎是与容器关联的迭代器值。这解释了为什么可解引用的值总是非奇异的:不指向任何容器的迭代器不能被解引用(这将返回什么元素?)。
正如 Matthieu M. 正确指出的那样,非奇异值可能仍然是不可解引用的。一个例子是尾后迭代器(可通过调用container.end()获得):它与容器关联,但仍然无法引用。
我无法说出这些术语的定义。然而,谷歌对“定义:单数”(以及其他定义)有这样的说法:
我想这可以解释这个术语。
Have a look at What is an iterator's default value?.
As the quote indicates, singular values are iterator values that are not associated with any container. A singular value is almost useless: you can't advance it, dereference it, etc. One way (the only way?) of getting a singular iterator is by not initializing it, as shown in templatetypedef's answer.
One of the useful things you can do with a singular iterator, is assign it a non-singular value. When you do that you can do whatever else you want with it.
The non-singular values are, almost by definition, iterator values that are associated with a container. This answers why dereferenceable values are always non-singular: iterators that do not point to any container cannot be dereferenced (what element would this return?).
As Matthieu M. correctly noted, non-singular values may still be non-dereferenceable. An example is the past-the-end iterator (obtainable by calling container.end()): it is associated with a container, but still cannot be referenced.
I can't say where these terms are defined. However, Google has this to say about "define: singular" (among other definitions):
I suppose this can explain the terminology.
让我们使用迭代器最简单的化身:指针。
对于指针:
NULL 值未初始化的值。我想说
NULL
指针是一个奇异值,尽管不是唯一的,因为它代表了价值的缺失。std::vector::iterator it;
,大多数迭代器(链接到容器的迭代器)的默认构造函数创建一个奇异值。由于它不依赖于容器,任何形式的导航(增量、减量……)都是毫无意义的。根据定义,奇异值表示不存在实际值。它们出现在许多语言中:Python 的
None
、C# 的null
、C 的NULL
、C++ 的std::nullptr
。问题是,在 C 或 C++ 中,它们也可能是简单的垃圾......(无论内存中之前有什么)我想不一定。标准没有要求它,人们可以想象使用哨兵对象。
Let us use the simplest incarnation of an
Iterator
: the pointer.For a pointer:
the NULL valuean uninitialized value.I would say that the
NULL
pointer is a singular value, though not the only one, since it represents the absence of value.std::vector<int>::iterator it;
, the default constructor of most iterators (those linked to a container) create a singular value. Since it's not tied to a container, any form of navigation (increment, decrement, ...) is meaningless.Singular values, by definition, represent the absence of a real value. They appear in many languages: Python's
None
, C#'snull
, C'sNULL
, C++'sstd::nullptr
. The catch is that in C or C++, they may also be simple garbage... (whatever was there in memory before)Not necessarily, I guess. It is not required by the standard, and one could imagine the use of a sentinel object.
如果我理解正确的话,迭代器的奇异值本质上相当于未分配的指针。它是一个尚未初始化为指向任何位置的迭代器,因此没有明确定义的迭代元素。例如,声明一个未设置为指向范围元素的新迭代器会将该迭代器创建为单个迭代器。
正如规范部分所提到的,单数迭代器是不安全的,并且不能对它们使用标准迭代器操作,例如增量、赋值等。您所能做的就是为它们分配一个新值,希望将它们指向有效的数据。
我认为有这个定义的原因是这样的声明
可以被规范允许,同时具有标准化的含义。这里的“奇异”一词可能是指奇点的数学定义,在不太正式的环境中也称为“不连续性”。
If I understand this correctly, a singular value for an iterator is essentially the equivalent of an unassigned pointer. It's an iterator that hasn't been initialized to point anywhere and thus has no well-defined element it's iterating over. Declaring a new iterator that isn't set up to point to an element of a range, for example, creates that iterator as a singular iterator.
As the portion of the spec alludes to, singular iterators are unsafe and none of the standard iterator operations, such as increment, assignment, etc. can be used on them. All you can do is assign them a new value, hopefully pointing them at valid data.
I think the reason for having this definition is so that statements like
Can be permitted by the spec while having standardized meaning. The term "singular" here probably refers to the mathematical definition of a singularity, which is also called a "discontinuity" in less formal settings.