迭代器的默认值是什么?

79

对于我使用的任何STL容器,如果我使用迭代器的默认构造函数声明一个该容器类型的迭代器,那么这个迭代器将被初始化为什么?

例如,我有:

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

iter将被初始化为什么?


std::list<void*>::iterator iter; 是一个定义。虽然所有的定义都是声明,但不是定义的声明将是:extern std::list<void*>::iterator iter; - sbi
特别是,构造函数属于_定义_,而不属于任何其他声明。这意味着你只能在(单个)定义中向构造函数传递值。此外,如果构造函数是一个模板(像这里一样),它会在定义的地方实例化。 - MSalters
3个回答

64

按照惯例,容器的“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 的情况下,一个默认构造的迭代器表示(与之相等)已经到达输入流的 EOF 的 istream_iterator

3
有一个提案希望创建一个值初始化的迭代器。请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3644.pdf。 - Ghita
4
根据该提案,编写"auto ni = vector<int>::iterator()"将创建一个空的vector<int>迭代器,其与同一类型的任何其他迭代器相等。 - Ghita
N3644 / 空指针前向迭代器自C++14以来就存在了。这似乎是答案,但如果我理解正确,那只适用于前向迭代器及更高版本(且仅自C++14起)。 - gast128

30

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

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


20
我又对标准用语产生了厌恶感。 <叹气> 这句话通俗易懂的意思是什么? - sbi
2
@sbi:好的,这段话继续说下去,我决定将其删减。基本上,您不能对单一值执行任何有用的操作,例如取消引用或比较。 - fredoverflow
11
@sbi:只需要将所有“singular”的实例替换为“weird”。由于其处于奇怪的状态,您不允许做任何其他操作。 - jalf
2
@jalf:感谢你澄清这一点。我认为“奇异值”是一个糟糕的名字,因为它可能有_任何_可能的值。它确实让我困惑了... - sbi
1
我能想到的唯一相关性是在线性代数的意义上,例如奇异矩阵是具有无限解的矩阵。 - Daniel B.
显示剩余5条评论

13

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


3
有没有一种方法将iter初始化为NULL? - The Void
3
@The Void:你的问题没有意义。NULL是指针可能具有的一个值,而不是迭代器。虽然所有指针都是迭代器,但并非所有迭代器都是指针。 - sbi
因此,虽然有所谓的NULL指针,但没有所谓的“NULL迭代器”? - The Void
2
@JesperE:很有可能已经初始化了(在许多情况下,迭代器是类,并且它们将具有初始化内容的默认构造函数)。 - David Rodríguez - dribeas
7
@sbi:bot是“但不是”的新缩写吗? :) - codymanix
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接