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

你缺少的是,在這個例子中,列表恰好包含兩個元素。如果您從兩個項目列表開始前進兩步,您應該在列表的末尾。這就是這個例子所說的。

如果你要前進兩個以上的步驟,你會在未定義的行爲土地,並斷言不再有任何意義。