STL 迭代器中的奇异值和非奇异值是什么?

发布于 2024-10-26 23:42:59 字数 614 浏览 3 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

z祗昰~ 2024-11-02 23:43:00

迭代器还可以具有不与任何容器关联的奇异值。

我想这就是它的定义。

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

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

Iterators can also have singular values that are not associated with any container.

I suppose that's its definition.

How and why dereferenceable values are always nonsingular?

Because if they wouldn't, dereferencing them would be undefined behavior.

不一样的天空 2024-11-02 23:43:00

查看迭代器的默认值是什么?

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

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

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

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

我无法说出这些术语的定义。然而,谷歌对“定义:单数”(以及其他定义)有这样的说法:

remarkable: unusual or striking

我想这可以解释这个术语。

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):

remarkable: unusual or striking

I suppose this can explain the terminology.

零度℉ 2024-11-02 23:43:00

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

让我们使用迭代器最简单的化身:指针。

对于指针:

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

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

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

std::vector::iterator it;,大多数迭代器(链接到容器的迭代器)的默认构造函数创建一个奇异值。由于它不依赖于容器,任何形式的导航(增量、减量……)都是毫无意义的。

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

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

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

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

What is singular value and nonsingular value? How are they defined? And where?

Let us use the simplest incarnation of an Iterator: the pointer.

For a pointer:

  • the singular value alluded to is the NULL value an uninitialized value.
  • a non-singular value is an explicitly initialized value, it may not be dereferencable still (the past-the-end pointer shall not be dereferenced)

I would say that the NULL pointer is a singular value, though not the only one, since it represents the absence of value.

What is the equivalence for regular iterators ?

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.

How and why dereferenceable values are always nonsingular ?

Singular values, by definition, represent the absence of a real value. They appear in many languages: Python's None, C#'s null, C's NULL, C++'s std::nullptr. The catch is that in C or C++, they may also be simple garbage... (whatever was there in memory before)

Is a default constructed iterator a singular value ?

Not necessarily, I guess. It is not required by the standard, and one could imagine the use of a sentinel object.

时间海 2024-11-02 23:42:59

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

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

我认为有这个定义的原因是这样的声明

set<int>::iterator itr;

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

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

set<int>::iterator itr;

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文