简体   繁体   English

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

[英]issue with std::advance on std::sets

I've stumbled upon what I believe is a bug in the stl algorithm advance . 我偶然发现了stl算法中的错误。

When I'm advancing the iterator off of the end of the container, I get inconsistent results. 当我将迭代器推进到容器的末尾时,得到的结果不一致。 Sometimes I get container.end(), sometimes I get the last element. 有时我得到container.end(),有时我得到最后一个元素。 I've illustrated this with the following code: 我用以下代码说明了这一点:

#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;
}

Which I get the following unexpected (according to me) behavior in experiment 3 and 5 where I get the last element instead of the_map.end(). 在实验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]$

From the sgi website (see link at top), it has the following example: 在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());

I would think that the assertion should apply to other container types, no? 我认为断言应适用于其他容器类型,不是吗?

What am I missing? 我想念什么?

Thanks! 谢谢!

There is no bug in the STL advance algorithm. STL高级算法中没有错误。

It's undefined what happens if you advance past the end of a collection. 如果您超过集合的末尾会发生什么,这是不确定的。

Undefined behavior is a common concept in C/C++, the results are always valid for undefined behavior, because... it is undefined behavior. 未定义行为是C / C ++中的一个常见概念,结果始终对未定义行为有效,因为...它是未定义行为。

You will likely have a bug in your program if you do something that gives undefined behavior. 如果您执行某些操作会带来不确定的行为,则可能会在程序中出现错误。

You are advancing the iterator past the end of the container. 您正在将迭代器推进到容器的末尾。 From the documentation: 从文档中:

If n > 0 it is equivalent to executing ++in times 如果n> 0,则等效于执行++

You don't have 100 elements in the container, but you are advancing the iterator 100 positions. 容器中没有100个元素,但您将迭代器的位置提高了100个。 It's not going to stop when it hits the end of the container because it doesn't know where the end of the container is. 当它碰到容器的末端时,它不会停止,因为它不知道容器的末端在哪里。

When I'm advancing the iterator off of the end of the container, ... 当我将迭代器移出容器的末端时,...

... you get undefined behavior . ...您得到不确定的行为 Whatever happens then, is fine according to the C++ standard. 然后,无论发生什么情况,根据C ++标准都可以。 That could be much worse than inconsistent results. 这可能比不一致的结果要糟糕得多。

What you are missing is that in the example the list contains exactly two elements. 您缺少的是在示例中,列表仅包含两个元素。 If you advance from the beginning of a two-item list by 2 steps, you should be at the end of the list. 如果您从两个项目的清单的开头前进2个步骤,则应该位于清单的结尾。 That's what the example asserts. 这就是该示例所断言的。

If you were to advance by more than two steps, you'd be in the undefined behavior land, and the assertion no longer makes any sense. 如果您要前进两个以上的步骤,那么您将处在未定义的行为范围内,并且断言不再有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM