奇异迭代器的赋值

Posted

技术标签:

【中文标题】奇异迭代器的赋值【英文标题】:Assignment of a Singular Iterator 【发布时间】:2015-12-22 00:04:37 【问题描述】:

一个“奇异迭代器”是defined as an:

不与任何序列关联的迭代器。空指针以及默认构造的指针(保存不确定值)都是单数

我的问题 1 是:默认构造的迭代器是否被视为“单一迭代器”?

其次,我一直told here那个:

大多数表达式的结果对于奇异值是未定义的;唯一的例外是销毁包含奇异值的迭代器,将非奇异值分配给包含奇异值的迭代器,并且对于满足 DefaultConstructible 要求的迭代器,使用值初始化的迭代器作为复制或移动操作。

问题 2 是:使用“未定义”的结果是否构成未定义行为? 如果这是真的,这将是未定义行为:

void* foo = nullptr;
auto bar = foo;

但是it runs fine。


我提出这个问题的更深层动机是在我有这样一个结构的情况下:

struct Foo 
    vector<int*>::const_iterator;
;

我想知道这样做是否是未定义的行为,其中assigned 是构造的值Foo 对象:

Foo unasigned;

assigned = unassigned;

如果问题 12 的答案是“是”,那么通过调用默认赋值运算符,我将引入未定义的行为 :(

【问题讨论】:

只是一个旁注:这不是因为它在某处运行良好,这不是 UB “默认构造的迭代器”是什么意思? 您应该包含您实际询问的代码,而不是做出模糊的陈述。 @HappyCoder vector&lt;int*&gt;::const_iterator foo; 是我所说的“默认构造的迭代器”。 该段对迭代器提出了一般要求——即,它们不需要支持超出指定值的奇异值的操作。具体的迭代器类型(例如指针)可以提供额外的保证。对于vector&lt;int*&gt;::const_iterator,它是一种实现定义的类型,您不能假设它的功能超出了标准的要求。 【参考方案1】:

问题 2 是:使用“未定义”的结果是否构成未定义行为?

答案是:肯定是的。在 UB 上工作就是 UB。

它似乎对你来说运行良好,因为它是未定义的。它可以做任何事情,包括按预期工作和不按预期工作。

【讨论】:

【参考方案2】:

关于第二个问题的示例,它可以正常工作,因为并且定义明确,因为您实际上并没有取消引用指针foo。变量foo 已初始化,您所做的只是用另一个已初始化的变量初始化一个变量。这和例如没有什么不同。

int foo = 0;
auto bar = foo;

但是,如果你这样做了,例如

int* foo = nullptr;
auto bar = *foo;

将是 UB,因为您取消引用空指针。

另外,未定义的行为,嗯,未定义...它可能看起来运行良好,但实际上并非如此。

【讨论】:

对,我不需要取消引用我的结构的 vector&lt;int*&gt;::const_iterator 成员的内容,所以我认为这意味着它的定义也很好? @JonathanMee 没错,如果你有一个默认初始化的迭代器,它仍然是初始化的,你可以将它用作分配的源。当您尝试执行任何其他操作(不仅包括取消引用)时,您将获得 UB。 我想相信该声明会简化我在代码中的许多问题。但是该声明与我在问题中的第二句话相冲突,不是吗? (虽然这句话可能已经过时了?我刚读到这个:en.cppreference.com/w/cpp/concept/…) @JoachimPileborg 否。在int *x, *y; 中,x 是默认初始化的,但根据适用的核心语言规则,y = x; 是 UB。这就是为什么迭代器子句需要值初始化的迭代器。

以上是关于奇异迭代器的赋值的主要内容,如果未能解决你的问题,请参考以下文章

用auto和iterator迭代器对元素赋值比较

装饰器生成器迭代器

迭代器的解释

问题记录

迭代器的学习心得

迭代器的学习心得