2010-03-27 61 views
1

我已经偶然发现了我认为是stl algorithm advance中的一个错误。问题与std :: advance std :: sets

当我将容器末端的迭代器推进时,出现不一致的结果。有时候我会得到container.end(),有时我会得到最后一个元素。我用下面的代码说明这一点:

#include <algorithm> 
#include <cstdio> 
#include <set> 

using namespace std; 
typedef set<int> tMap; 

int main(int argc, char** argv) 
{ 
    tMap::iterator i; 
    tMap the_map; 

    for (int i=0; i<10; i++) 
     the_map.insert(i); 

#if EXPERIMENT==1 
    i = the_map.begin(); 
#elif EXPERIMENT==2 
    i = the_map.find(4); 
#elif EXPERIMENT==3 
    i = the_map.find(5); 
#elif EXPERIMENT==4 
    i = the_map.find(6); 
#elif EXPERIMENT==5 
    i = the_map.find(9); 
#elif EXPERIMENT==6 
    i = the_map.find(2000); 
#else 
    i = the_map.end(); 
#endif 

    advance(i, 100); 

    if (i == the_map.end()) 
     printf("the end\n"); 
    else 
     printf("wuh? %d\n", *i); 

    return 0; 
} 

其中我得到实验3以下意外(根据我的)行为和5从哪里获得的最后一个元素,而不是the_map.end的()。

[[email protected] advance]$ uname -srvmpio 
Linux 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:37:32 EDT 2006 i686 athlon i386 GNU/Linux 
[[email protected] advance]$ g++ --version 
g++ (GCC) 4.1.1 20061011 (Red Hat 4.1.1-30) 
Copyright (C) 2006 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

[[email protected] advance]$ g++ -DEXPERIMENT=1 advance.cc 
[[email protected] advance]$ ./a.out 
the end 
[[email protected] advance]$ g++ -DEXPERIMENT=2 advance.cc 
[[email protected] advance]$ ./a.out 
the end 
[[email protected] advance]$ g++ -DEXPERIMENT=3 advance.cc 
[[email protected] advance]$ ./a.out 
wuh? 9 
[[email protected] advance]$ g++ -DEXPERIMENT=4 advance.cc 
[[email protected] advance]$ ./a.out 
the end 
[[email protected] advance]$ g++ -DEXPERIMENT=5 advance.cc 
[[email protected] advance]$ ./a.out 
wuh? 9 
[[email protected] advance]$ g++ -DEXPERIMENT=6 advance.cc 
[[email protected] advance]$ ./a.out 
the end 
[[email protected] advance]$ g++ -DEXPERIMENT=7 advance.cc 
[[email protected] advance]$ ./a.out 
the end 
[[email protected] advance]$ 

从SGI网站(见顶部链接),它有下面的例子:

list<int> L; 
L.push_back(0); 
L.push_back(1); 

list<int>::iterator i = L.begin(); 
advance(i, 2); 
assert(i == L.end()); 

我认为,断言应适用于其他容器类型,不是吗?

我错过了什么?

谢谢!

回答

2

当我前进的迭代器从容器的结束,...

...你未定义行为。无论发生什么,根据C++标准都是很好的。那可能是much worse比不一致的结果。

6

STL高级算法没有缺陷。

这是不确定的,如果你超过集合的末尾会发生什么。

未定义的行为是C/C++中的一个常见概念,结果对于未定义的行为总是有效的,因为......它是未定义的行为。

如果您执行某些未定义的行为,那么您的程序中可能会有一个错误。

2

您正在推进迭代器超过容器的末尾。从文档:

如果n> 0,则是相当于执行++ I N次

您不必在容器中100个元素,但你在前进迭代器100个职位。当它碰到容器的末端时不会停止,因为它不知道容器的末端在哪里。

0

你缺少的是,在这个例子中,列表恰好包含两个元素。如果您从两个项目列表开始前进两步,您应该在列表的末尾。这就是这个例子所说的。

如果你要前进两个以上的步骤,你会在未定义的行为土地,并断言不再有任何意义。