奇异迭代器的赋值
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;
如果问题 1 和 2 的答案是“是”,那么通过调用默认赋值运算符,我将引入未定义的行为 :(
【问题讨论】:
只是一个旁注:这不是因为它在某处运行良好,这不是 UB “默认构造的迭代器”是什么意思? 您应该包含您实际询问的代码,而不是做出模糊的陈述。 @HappyCodervector<int*>::const_iterator foo;
是我所说的“默认构造的迭代器”。
该段对迭代器提出了一般要求——即,它们不需要支持超出指定值的奇异值的操作。具体的迭代器类型(例如指针)可以提供额外的保证。对于vector<int*>::const_iterator
,它是一种实现定义的类型,您不能假设它的功能超出了标准的要求。
【参考方案1】:
问题 2 是:使用“未定义”的结果是否构成未定义行为?
答案是:肯定是的。在 UB 上工作就是 UB。
它似乎对你来说运行良好,因为它是未定义的。它可以做任何事情,包括按预期工作和不按预期工作。
【讨论】:
【参考方案2】:关于第二个问题的示例,它可以正常工作,因为并且定义明确,因为您实际上并没有取消引用指针foo
。变量foo
已初始化,您所做的只是用另一个已初始化的变量初始化一个变量。这和例如没有什么不同。
int foo = 0;
auto bar = foo;
但是,如果你这样做了,例如
int* foo = nullptr;
auto bar = *foo;
那 将是 UB,因为您取消引用空指针。
另外,未定义的行为,嗯,未定义...它可能看起来运行良好,但实际上并非如此。
【讨论】:
对,我不需要取消引用我的结构的vector<int*>::const_iterator
成员的内容,所以我认为这意味着它的定义也很好?
@JonathanMee 没错,如果你有一个默认初始化的迭代器,它仍然是初始化的,你可以将它用作分配的源。当您尝试执行任何其他操作(不仅包括取消引用)时,您将获得 UB。
我想相信该声明会简化我在代码中的许多问题。但是该声明与我在问题中的第二句话相冲突,不是吗? (虽然这句话可能已经过时了?我刚读到这个:en.cppreference.com/w/cpp/concept/…)
@JoachimPileborg 否。在int *x, *y;
中,x
是默认初始化的,但根据适用的核心语言规则,y = x;
是 UB。这就是为什么迭代器子句需要值初始化的迭代器。以上是关于奇异迭代器的赋值的主要内容,如果未能解决你的问题,请参考以下文章