奇异迭代器的赋值

Assignment of a Singular Iterator

提问人:Jonathan Mee 提问时间:9/24/2015 最后编辑:CommunityJonathan Mee 更新时间:9/24/2015 访问量:499

问:

“奇异迭代器”被定义为

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

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

其次,我在这里被告知

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

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

void* foo = nullptr;
auto bar = foo;

但它运行良好


我问这个问题的更深层次的动机是,我有一个这样的结构:

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

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

Foo unasigned;

assigned = unassigned;

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

C++ 迭代器 赋值运算符 default-constructor singular

评论

1赞 Thomas Ayoub 9/24/2015
只是一个旁注:这并不是因为它在某个地方运行良好,所以这不是 UB
0赞 CinCout 9/24/2015
“默认构造的迭代器”是什么意思?
0赞 Barry 9/24/2015
你应该包括你实际询问的代码,而不是做出模糊的陈述。
0赞 Jonathan Mee 9/24/2015
@HappyCoder这就是我所说的“默认构造迭代器”所指的。vector<int*>::const_iterator foo;
2赞 T.C. 9/26/2015
该段落对迭代器提出了一般要求,即,它们不需要支持具有超出指定值的奇异值的操作。具体迭代器类型(如指针)可能会提供额外的保证。对于 ,它是一种实现定义的类型,您不能假设它所做的任何事情都超出了标准的要求。vector<int*>::const_iterator

答:

0赞 CinCout 9/24/2015 #1

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

答案是:绝对是的。在 UB 上工作是 UB。

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

0赞 Some programmer dude 9/24/2015 #2

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

int foo = 0;
auto bar = foo;

但是,如果您这样做,例如

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

这将是 UB,因为您取消了对空指针的引用。

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

评论

0赞 Jonathan Mee 9/24/2015
对,我不需要取消引用我的结构成员的内容,所以我认为这意味着它也定义得很好?vector<int*>::const_iterator
1赞 Some programmer dude 9/24/2015
@JonathanMee 没错,如果你有一个默认初始化的迭代器,它仍然会初始化,你可以将其用作赋值的源。当您尝试执行任何其他操作(包括不仅仅是取消引用)时,您就会获得 UB。
0赞 Jonathan Mee 9/24/2015
我想相信这句话,因为它简化了我在代码中的很多问题。但是这种说法与我在问题中的第二句话相冲突,不是吗?(虽然也许这句话已经过时了?我刚刚读到这个:en.cppreference.com/w/cpp/concept/......)
1赞 T.C. 9/26/2015
@JoachimPileborg 编号在 中,是默认初始化的,但根据适用的核心语言规则是 UB。这就是迭代器子句需要值初始化迭代器的原因。int *x, *y;xy = x;