提问人:fredoverflow 提问时间:1/11/2011 更新时间:1/10/2019 访问量:12393
比较不同容器的迭代器
comparing iterators from different containers
问:
比较不同容器的迭代器是否合法?
std::vector<int> foo;
std::vector<int> bar;
表达式是否会产生错误或未定义的行为?foo.begin() == bar.begin()
(我正在编写一个自定义迭代器,在实现时偶然发现了这个问题。operator==
答:
不。如果它是合法的,这将意味着指针不会是迭代器。
评论
int a, b; &a == &b;
operator =
&a == &b
a == b
不能直接比较不同容器中的迭代器。迭代器是使用容器的内部状态来遍历容器的对象;将一个容器的内部结构与另一个容器进行比较根本没有意义。
但是,如果生成的迭代器可用,则通过遍历的对象计数与当前迭代器值来比较迭代器可能是有意义的。这是使用以下方法完成的:container.begin()
begin()
std::distance
int a = std::distance(containerA.begin(), iteratorA);
int b = std::distance(containerB.begin(), iteratorB);
if (a <comparison> b)
{ /* ... */ }
如果没有更多的背景信息,就很难判断这是否能解决你的问题。
评论
ISO/IEC 14882:2003(E) 5.10.1 标准
==(等于)和 !=(不等于)运算符与关系运算符具有相同的语义限制、转换和结果类型,只是它们的优先级和真值结果较低。[ .. ]可以比较指向相同类型的对象或函数的指针(指针转换后)是否相等。当且仅当两个相同类型的指针都为 null、都指向同一函数或都表示相同的地址 (3.9.2) 时,它们才相等。
XCode (3.2.3) 上的仿真结果:
#include <iostream>
#include <vector>
int main()
{
std::vector <int> a,aa;
std::vector <float> b;
if( a.begin() == aa.begin() )
std::cout << "\n a.begin() == aa.begin() \n" ;
a.push_back(10) ;
if( a.begin() != aa.begin() )
std::cout << "\n After push back a.begin() != aa.begin() \n" ;
// Error if( a.begin() == b.begin() )
return 0;
}
输出:
a.begin() == aa.begin() 推回 a.begin() 后 != aa.begin()
评论
std::list<T>::iterator
but need not be the other way around
我没有从标准的 100% 中得到对输入迭代器的要求,但从那里开始(正向/双向/随机访问迭代器)对 == 的域没有要求,因此它必须在等价关系中返回错误结果。但是,您不能对来自不同容器的迭代器进行<、>或减法。
编辑:它不必返回 false,它必须产生等价关系,这允许两个空容器进行比较相等(如另一个答案所示)。如果迭代器是可反引用的,则必须保持。这仍然不是未定义的行为。.begin()
a == b => *a == *b
评论
The domain of == for forward iterators is that of iterators over the same underlying sequence.
§ 24.2.5 (C++0x)
==
==
==
据我所知,未定义的行为。在 VS 2010 中
/*
* to disable iterator checking that complains that the iterators are incompatible (come from * different containers :-)
*/
#define _HAS_ITERATOR_DEBUGGING 0
std::vector<int> vec1, vec2;
std::vector<int>::iterator it1 = vec1.begin();
std::vector<int>::iterator it2 = vec2.begin();
if (it1 == it2)
{
std::cout << "they are equal!!!";
}
在本例中,相等性测试返回 true :-),因为容器是空的,迭代器的_Ptr成员都是 nullptr。
谁知道也许你的实现以不同的方式做事,测试会返回 false :-)。
编辑:
请参阅 C++ 标准库活动问题列表“446。不同容器之间的迭代器相等”。也许有人可以检查标准,看看是否采用了更改?
可能不是,因为它在活动问题列表中,所以查尔斯·贝利(Charles Bailey)也回答了这个问题,这是对的,这是未指明的行为。
所以我想行为可能不同(至少在理论上)不同实现之间,这只是一个问题。
事实上,在 VS 检查附带的 STL 实现中启用迭代器调试后,对于这种确切的情况(来自不同容器的迭代器)来说,至少对我来说,至少再次表明,应尽可能避免进行此类比较。
评论
我认为这是未指定的行为(C++03)。 迭代器是随机访问迭代器,其行为在正向迭代器的要求中定义。std::vector
==
== 是等价关系
请注意,这是对类型的要求,因此必须(在本例中)适用于任何一对有效的(可取消引用或其他方式)。我相信这意味着必须给你一个/答案,不能引起UB。std::vector::iterator
==
true
false
— 如果 a 和 b 相等,则 a 和 b 都是可取消引用的,否则两者都不可取消引用。
相反,可取消引用的迭代器不能与不可取消引用的迭代器进行比较。
— 如果 a 和 b 都是可取消引用的,则 a == b 当且仅当 *a 和 *b 是同一个对象。
请注意,对于两个不可取消引用的迭代器,没有要求。只要是传递的(如果和然后)、反身的()和对称的(如果那么),不同容器的某些、全部或没有迭代器是否相等都无关紧要。a == b
==
a.end() == b.end()
b.end() == c.end()
a.end() == c.end()
a.end() == a.end()
a.end() == b.end()
b.end() == a.end()
end()
另请注意,这与 . 用 来定义,其中 和 都是随机访问迭代器。执行的前提条件是必须有一个值,该值要求 和 成为相同范围内的迭代器。<
<
b - a
a
b
b - a
Distance
n
a + n == b
a
b
评论
a == b
*a == *b
*a == *b
如果考虑 C++11 标准 (n3337):
当且仅当表达式存在有限的应用序列时,迭代器才被称为可从迭代器访问。如果可从 到达,则它们引用相同序列的元素。
j
i
++i
i == j
j
i
§ 24.2.5 — [forward.iterators#2]
对于正向迭代器的域是同一基础序列上的迭代器域。
==
鉴于 必须满足 施加的所有要求,则比较来自不同容器的迭代器是不确定的。RandomAccessIterator
ForwardIterator
LWG 问题 #446 专门讨论了这个问题,建议在标准中添加以下文本(感谢 @Lightness Races in Orbit 引起注意):
除非另有明确说明,否则直接或间接计算任何比较函数或二进制运算符的结果,该运算符具有两个迭代器值作为参数,这些参数是从两个不同的范围 r1 和 r2(包括它们的结束值)获得的,这些值不是一个公共范围的子范围。
评论
上一个:C++ 继承问题
下一个:make_unique完美转发
评论