[英]issue with std::advance on std::sets
我偶然发现了stl算法中的错误。
当我将迭代器推进到容器的末尾时,得到的结果不一致。 有时我得到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()。
[tim@saturn 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
[tim@saturn 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.
[tim@saturn advance]$ g++ -DEXPERIMENT=1 advance.cc
[tim@saturn advance]$ ./a.out
the end
[tim@saturn advance]$ g++ -DEXPERIMENT=2 advance.cc
[tim@saturn advance]$ ./a.out
the end
[tim@saturn advance]$ g++ -DEXPERIMENT=3 advance.cc
[tim@saturn advance]$ ./a.out
wuh? 9
[tim@saturn advance]$ g++ -DEXPERIMENT=4 advance.cc
[tim@saturn advance]$ ./a.out
the end
[tim@saturn advance]$ g++ -DEXPERIMENT=5 advance.cc
[tim@saturn advance]$ ./a.out
wuh? 9
[tim@saturn advance]$ g++ -DEXPERIMENT=6 advance.cc
[tim@saturn advance]$ ./a.out
the end
[tim@saturn advance]$ g++ -DEXPERIMENT=7 advance.cc
[tim@saturn advance]$ ./a.out
the end
[tim@saturn 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());
我认为断言应适用于其他容器类型,不是吗?
我想念什么?
谢谢!
STL高级算法中没有错误。
如果您超过集合的末尾会发生什么,这是不确定的。
未定义行为是C / C ++中的一个常见概念,结果始终对未定义行为有效,因为...它是未定义行为。
如果您执行某些操作会带来不确定的行为,则可能会在程序中出现错误。
您正在将迭代器推进到容器的末尾。 从文档中:
如果n> 0,则等效于执行++
容器中没有100个元素,但您将迭代器的位置提高了100个。 当它碰到容器的末端时,它不会停止,因为它不知道容器的末端在哪里。
当我将迭代器移出容器的末端时,...
...您得到不确定的行为 。 然后,无论发生什么情况,根据C ++标准都可以。 这可能比不一致的结果要糟糕得多。
您缺少的是在示例中,列表仅包含两个元素。 如果您从两个项目的清单的开头前进2个步骤,则应该位于清单的结尾。 这就是该示例所断言的。
如果您要前进两个以上的步骤,那么您将处在未定义的行为范围内,并且断言不再有意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.