比较来自不同容器的迭代器

比较不同容器的迭代器是否合法?

std::vector<int> foo; std::vector<int> bar; 

expression式foo.begin() == bar.begin()产生错误或未定义的行为?

(我正在写一个自定义的迭代器,并且在实现operator==时候偶然发现了这个问题。)

如果您考虑C ++ 0x草稿:

§24.2.1

迭代器j被称为从迭代器可达我当且仅当有一个有限的序列的应用程序的expression式++ i,使i == j。 如果j从i可到达,则它们指的是相同序列的元素。

§24.2.5

前向迭代器的==域是相同基础序列上的迭代器的域。

鉴于RandomAccessIterator必须满足由ForwardIterator强加的所有要求,比较来自不同容器的迭代器是未定义的。

据我所知,未定义的行为。 在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!!!"; } 

在这种情况下,相等性testing返回true :-),因为容器是空的,迭代器的_Ptr成员都是nullptr。

谁知道你的实现可能会做不同的事情,testing会返回false :-)。

编辑:

请参阅C ++标准库“活动问题”列表 “446.不同容器之间的迭代器相等”。 也许有人可以检查标准,看看是否采纳了变化?

可能没有,因为它是在积极的问题清单,所以查尔斯贝利谁也回答这是正确的,这是不明确的行为。

所以我猜想不同的实现可能会有不同(至less在理论上),这只是一个问题。

事实上,在VS检查中的STL实现中启用了迭代器debugging,对于这种确切的情况(来自不同容器的迭代器)至less对我来说,应该尽可能地避免这种比较。

你不能直接比较不同容器的迭代器。 迭代器是一个使用容器的内部状态来遍历它的对象; 比较一个容器的内部到另一个容器根本没有意义。

但是,如果container.begin()产生的迭代器可用,则可以通过从begin()到当前迭代器值的对象的计数比较迭代器。 这是使用std::distance

 int a = std::distance(containerA.begin(), iteratorA); int b = std::distance(containerB.begin(), iteratorB); if (a <comparison> b) { /* ... */ } 

没有更多的背景,很难判断这是否能解决你的问题。 因人而异。

我相信这是不明确的行为(C ++ 03)。 std::vector迭代器是随机访问迭代器, ==的行为是在forward迭代器的需求中定义的。

==是等价关系

请注意,这是一个types的要求,所以必须适用于(在这种情况下)任何有效的(无法引用或以其他方式) std::vector::iterator s对。 我相信这意味着==必须给你一个true / false答案,并不会导致UB。

– 如果a和b相等,则a和b都是可引用的,否则两者都不可引用。

相反,可解引用的迭代器不能与不可解引用的迭代器进行比较。

– 如果a和b都是可解引用的,则a == b当且仅当* a和* b是同一个对象。

请注意,对于两个不可解引用的迭代器,是否缺lessa == 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定义,其中ab都是随机访问迭代器。 执行b - a先决条件是必须有一个Distancen ,使得a + n == b需要ab为迭代器到相同的范围。

不。如果这是合法的,这意味着指针不会是迭代器。

ISO / IEC 14882:2003(E)5.10.1

==(等于)和!=(不等于)运算符与关系运算符具有相同的语义限制,转换和结果types,除了它们的优先级较低和真值结果之外。 指向相同types的对象或函数(指针转换之后)的指针可以相等进行比较。 相同types的两个指针比较相等的当且仅当它们都是空的,都指向相同的函数,或者两者都代表相同的地址(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()

我没有从标准的100%获得对input迭代器的要求,但是从那里(正向/双向/随机访问迭代器),对==域没有要求,所以它必须返回假 等式关系结果 。 你不能对不同容器的迭代器进行<或>或减法运算。

编辑:它不必返回false,它必须导致一个等价关系,这允许两个空容器的.begin()比较相等(如另一个答案所示)。 如果迭代器是可取的, a == b => *a == *b必须保持。 这仍然是不确定的行为。