【发布时间】:2010-10-25 02:12:05
【问题描述】:
我想知道,如何为 STL 迭代器建立相等 (==)? 它是简单的指针比较(因此基于地址)还是更花哨的东西?
如果我有来自两个不同列表对象的两个迭代器并比较它们,结果是否总是错误的?
如果我将有效值与超出范围的值进行比较会怎样?总是假的吗?
【问题讨论】:
我想知道,如何为 STL 迭代器建立相等 (==)? 它是简单的指针比较(因此基于地址)还是更花哨的东西?
如果我有来自两个不同列表对象的两个迭代器并比较它们,结果是否总是错误的?
如果我将有效值与超出范围的值进行比较会怎样?总是假的吗?
【问题讨论】:
如果需要,迭代器类可以定义重载的 == 运算符。所以结果取决于operator==的实现。
您实际上不应该比较来自不同容器的迭代器。如果你这样做,我认为一些调试 STL 实现会发出警告,这将帮助你在代码中发现这种错误使用的情况。
【讨论】:
std::copy时会发出恼人的弃用警告...
丹尼尔问: 我想知道,如何为 STL 迭代器建立平等(==)?它是简单的指针比较(因此基于地址)还是更花哨的东西?
这取决于实施。现在,在 Visual C++ 2008 上,我看到以下代码(用于列表迭代器):
bool operator==(const _Myt_iter& _Right) const
{ // test for iterator equality
#if _HAS_ITERATOR_DEBUGGING
_Compat(_Right);
#else
_SCL_SECURE_TRAITS_VALIDATE(this->_Has_container() && this->_Same_container(_Right));
#endif /* _HAS_ITERATOR_DEBUGGING */
return (_Ptr == _Right._Ptr);
}
您将在上面看到验证迭代器有效性的代码和_Ptr 是指向列表节点的指针。
所以我想既有验证,也有简单的原始指针比较。
丹尼尔问: 如果我有来自两个不同列表对象的两个迭代器并比较它们,结果是否总是错误的?
到目前为止,该标准似乎在该主题上有些不清楚。显然,他们会明确写出这种操作有未定义的结果:
引用:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#446
使用任何迭代器操作的结果 (24.2.1 [input.iterators], 24.2.2 [output.iterators], 24.2.3 [forward.iterators], 24.2.4 [bidirectional .iterators], 24.2.5 [random.access.iterators]) 使用两个迭代器值作为参数(脚注)从两个不同的范围获得 r1 和 r2 (包括它们的过去值)不是一个公共范围的子范围未定义,除非另有明确说明。
footnote) 这些操作包括 ==、
所以我想比较来自不同容器的迭代器是邪恶的...... ^_^
丹尼尔问: 如果我将一个有效值与一个超出范围的值进行比较怎么办?总是假的吗?
同上。
【讨论】:
我想知道,如何为 STL 迭代器建立相等 (==)?
并非所有迭代器都可以进行比较(例如,输出迭代器不需要提供op==)。当范围的概念为正在考虑的迭代器类别明确定义时,您可以使用operator==。
是简单的指针比较(因此基于地址)还是更花哨的东西?
迭代器总是用指针实现的。编辑:我说 implemented with - 这不是指标准要求,而是指使用 poitners 作为底层构造的做法。不过,实现(如 VS)可能会插入特殊的验证检查。
如果我有来自两个不同列表对象的两个迭代器并比较它们,结果是否总是错误的?
您正在调用未定义的行为。
如果我将有效值与超出范围的值进行比较会怎样?总是假的吗?
再次,您将调用 UB。唯一有效的比较是在同一范围内的两个迭代器之间或在范围内的一个迭代器和另一个与最后一个元素之后的迭代器之间进行比较。请注意,您只能将迭代器与最后一个元素进行比较,取消引用相同的导致 UB。
【讨论】:
相等性测试特定于您正在使用的迭代器类型,或者可能根本不存在。如果你真的想知道,你可以随时查看你正在使用的 STL 的实现源代码,在迭代器类中查找 operator==()。
迭代器并不总是指针,事实上在某些“安全”版本的 STL 中,迭代器从不是指针。向量和字符串的迭代器通常被实现为指针,因为它们可以。用于双端队列、列表、集合和映射的迭代器在任何半有效实现中都不能是指针。
迭代器是一种智能指针。它们遵循一般原则,即如果它们的外观和行为都像指针,那么就用户而言,它们是指针。
【讨论】: