std :: advance在std :: sets上的问题

时间:2010-03-27 20:21:44

标签: c++ stl

我偶然发现了我认为stl algorithm advance中的错误。

当我从容器末端推进迭代器时,我得到的结果不一致。有时候我得到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());

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

我错过了什么?

谢谢!

4 个答案:

答案 0 :(得分:6)

STL高级算法中没有错误。

如果你超越集合的结尾,那么会发生什么。

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

如果你做了一些提供未定义行为的事情,你的程序可能会有错误。

答案 1 :(得分:2)

您正在将迭代器推进到容器的末尾。来自文档:

  

如果n> 0相当于执行++ i n次

容器中没有100个元素,但是你正在推进迭代器100的位置。当它碰到容器的末端时它不会停止,因为它不知道容器的末端在哪里。

答案 2 :(得分:2)

  

当我从容器末端推进迭代器时,......

...你得到未定义的行为。无论发生什么,根据C ++标准都可以。这可能是much worse而不是不一致的结果。

答案 3 :(得分:0)

您缺少的是,在示例中,列表恰好包含两个元素。如果您从两项目列表的开头前进两步,则应该位于列表的末尾。这就是示例断言的内容。

如果你要超过两步,那么你将处于未定义的行为范围内,并且断言不再有任何意义。