迭代器的默认值是多少?


69

对于我正在使用的任何STL容器,如果我使用迭代器的默认构造函数声明一个(此特定容器类型的)迭代器,则该迭代器将初始化为什么?

例如,我有:

std::list<void*> address_list;
std::list<void*>::iterator iter;

将初始化什么?


std::list<void*>::iterator iter;是一个定义。尽管所有定义都是声明,但不是定义的声明将是:extern std::list<void*>::iterator iter;
2010年

特别是,构造函数属于定义,而不属于任何其他声明。这意味着您只能在(单个)定义中将值传递给构造函数。另外,如果ctor是模板(如此处),则会在定义所在的位置进行实例化。
MSalters 2010年

Answers:


55

按照惯例,容器的“ NULL迭代器”用于表示没有结果,其结果等于的结果container.end()

 std::vector<X>::iterator iter = std::find(my_vec.begin(), my_vec.end(), x);
 if (iter == my_vec.end()) {
     //no result found; iter points to "nothing"
 }

但是,由于默认构造的容器迭代器未与任何特定容器相关联,因此它可能没有很好的价值。因此,它只是一个未初始化的变量,唯一合法的操作是为其分配一个有效的迭代器。

 std::vector<X>::iterator iter;  //no particular value
 iter = some_vector.begin();  //iter is now usable

对于其他类型的迭代器,可能并非如此。例如,在情况下istream_iterator,默认构造的迭代器表示(比较等于)istream_iterator已达到输入流的EOF的。


3
有一个建议是存在一个值初始化的迭代器。参见open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3644.pdf
Ghita

4
根据该建议,自动编写ni = vector <int> :: iterator()将创建一个空的vector <int>迭代器,该迭代器将与任何其他相同类型的迭代器进行比较
Ghita 2015年

从C ++ 14开始存在N3644 /空正向迭代器。这似乎就是这个答案,但如果我理解正确,那仅适用于正向迭代器和更好的迭代器(并且仅适用于C ++ 14)。
gast128 '20

27

默认的构造函数将迭代器初始化为一个奇异值

迭代器还可以具有不与任何序列关联的奇异值。 [示例:在声明未初始化的指针x(如int* x;)之后, x必须始终假定其具有指针的奇异值。—最终示例]
对于奇异值,大多数表达式的结果均未定义 [24.2.1§5]


17
我的标准反感再度来袭。<sigh>可理解的语音是什么意思?
2010年

2
@sbi:好吧,该段继续进行,我决定删掉它。基本上,不允许您对奇异值做任何有用的事情,例如取消引用或比较它。
fredoverflow

10
@sbi:只需将所有“奇异”实例替换为“怪异”即可。您无法对其进行任何操作,因为它处于怪异状态。
jalf

1
@杰夫和弗雷德:谢谢。有趣。我当然从来没有遇到过“单一价值”一词。这是否意味着某个特定的value_(NULL对于指针而言)?我以为T*是有效的类型std::vector<T>::iterator?(以前的Dinkumware实现曾经这样做。)如果是这样,那么std::vector<T>::iterator it;肯定不会初始化it为特殊值std::vector<T>::iterator it = std::vector<T>::iterator();
2010年

2
@jalf:感谢您澄清这一点。对于可能具有任何可能值的事物,我认为“奇异值”是一个不好的名字。它肯定让我失望了……
。–

12

迭代器未初始化,就像int x;声明未初始化的整数一样。它没有正确定义的值。


3
有没有办法将iter初始化为NULL?
空虚2010年

3
@虚空:您的问题毫无道理。bot迭代器NULL指针可能具有的值。尽管所有指针都是迭代器,但并非所有迭代器都是指针。
2010年

因此,尽管存在诸如NULL指针之类的东西,却没有诸如“ NULL迭代器”之类的东西?
空虚2010年

2
@JesperE:它很可能已初始化(在许多情况下,迭代器是类,并且它们将具有用于初始化内容的默认构造函数)。
大卫·罗德里格斯(DavidRodríguez)-dribeas 2010年

5
@sbi:机器人是“但不是”的新缩写吗?:)
codymanix

0

更新的答案。

直到C ++ 11(包括C ++ 11):默认和值初始化的迭代器可能包含一个奇异值。从技术上讲,它不能被比较或取消引用。参见[iterator.requirements.general] / p5

但是,按照约定,STL实现用于将此类迭代器初始化为过去的迭代器。

C ++ 14开始:值初始化的正向迭代器比较等于过去的迭代器。参见[iterators.forward.iterators] / p2

...值初始化的迭代器可以进行比较,并且应与相同类型的其他值初始化的迭代器进行比较。[注意:值初始化的迭代器的行为就像它们引用了同一空序列的末尾一样。  —尾注]

因此:

std::list<void*>::iterator iter {};应该作为过去的迭代器。

std::list<void*>::iterator iter;这是危险的,因为iter只有在具有非平凡的默认构造函数的情况下才会进行初始化。尽管std::list可能是这种情况,所以也应该起作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.