Iteratory w C++ (stl) vs Java, czy jest jakaś różnica pojęciowa?

Wracam do c++ po tym, jak wyjechałem na chwilę i próbowałem odkurzyć Stary melon.

W języku Java Iterator jest interfejsem do kontenera posiadającego metody: hasNext (), next () I remove (). Obecność hasNext() oznacza, że ma pojęcie granicy dla przejeżdżającego kontenera.

//with an Iterator
Iterator<String> iter = trees.iterator();
while (iter.hasNext()) 
{
    System.out.println(iter.next());
}

W standardowej bibliotece szablonów C++ Iteratory wydają się reprezentować typ danych lub klasę, która obsługuje operator++ i operator==, ale nie ma żadnej koncepcji ograniczenia zbudowany w ten sposób porównanie jest wymagane przed przejściem do następnego elementu. Limit musi zostać sprawdzony przez użytkownika porównując dwa Iteratory w normalnym przypadku drugi iterator jest końcem kontenera.

vector<int> vec;
vector<int>::iterator iter;

// Add some elements to vector
v.push_back(1);
v.push_back(4);
v.push_back(8);

for(iter= v.begin(); iter != v.end(); iter++)
{
    cout << *i << " "; //Should output 1 4 8
}

Interesujące jest to, że w C++ wskaźnik jest iteratorem tablicy. STL wziął to, co było istniejące i zbudował konwencję wokół niego.

Czy jest w tym jeszcze jakaś subtelność, której mi brakuje?
Author: JeffV, 2008-09-11

9 answers

Tak, Istnieje duża różnica pojęciowa. C++ wykorzystuje różne" klasy " iteratorów. Niektóre są używane do dostępu losowego( w przeciwieństwie do Javy), niektóre są używane do dostępu do przodu (jak java). Podczas gdy nawet inne są używane do zapisu danych (do użytku z, powiedzmy, transform).

Zobacz koncepcję iteratorów w dokumentacji C++ :

  • Input Iterator
  • Iterator Wyjściowy
  • Forward Iterator
  • Iterator Dwukierunkowy
  • Dostęp Losowy Iterator
Są one o wiele ciekawsze i bardziej wydajne w porównaniu do słabych iteratorów Java/C#. Miejmy nadzieję, że konwencje te zostaną skodyfikowane przy użyciu C++0x.
 18
Author: Frank Krueger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-26 16:43:24

Może trochę bardziej teoretyczne. Matematycznie zbiory w C++ można opisać jako półotwarty interwał iteratorów, mianowicie jeden iterator wskazujący na początek zbioru i jeden iterator wskazujący tuż za ostatnim elementem.

Ta konwencja otwiera wiele możliwości. Sposób działania algorytmów w C++, można je wszystkie zastosować do większej kolekcji. Aby takie coś działało w Javie, musisz utworzyć wrapper wokół istniejącego kolekcja zwracająca inny iterator.

Kolejny ważny aspekt iteratorów został już wspomniany przez Franka. Istnieją różne koncepcje iteratorów. Iteratory Javy odpowiadają iteratorom wejściowym C++, tzn. są to Iteratory tylko do odczytu, które mogą być zwiększane tylko krok po kroku i nie mogą się cofać.

Z drugiej strony, masz wskaźniki C, które odpowiadają dokładnie koncepcji C++' losowego iteratora dostępu.

Podsumowując, C++ oferuje wiele bogatsza i czystsza koncepcja, która może być stosowana do znacznie szerszej gamy zadań niż wskaźniki C lub Iteratory Javy.

 20
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 12:29:48

Jak wspomniano, Iteratory Java i C# opisują mieszaną pozycję (Stan) i zakres (wartość), podczas gdy Iteratory C++ oddzielają pojęcia position i range. Iteratory C++ reprezentują "where am I now" oddzielnie od " where can I go?'.

Iteratory Java i C# nie mogą być kopiowane. Nie możesz odzyskać poprzedniej pozycji. Wspólne Iteratory C++ mogą.

Rozważ Ten przykład :

// for each element in vec
for(iter a = vec.begin(); a != vec.end(); ++a){
  // critical step!  We will revisit 'a' later.
  iter cur = a; 
  unsigned i = 0;
  // print 3 elements
  for(; cur != vec.end() && i < 3; ++cur, ++i){
      cout << *cur << " ";
  }
  cout << "\n";
}

Kliknij powyższy link, aby zobaczyć wynik programu.

To dość głupia pętla przechodzi przez sekwencję (używając tylko semantyki forward iterator), drukując każdą ciągłą sekwencję 3 elementów dokładnie raz (i kilka krótszych sekwencji na końcu). Ale przypuśćmy, że N elementów i m elementów na linię zamiast 3, algorytm ten nadal byłby O (N*m) przyrostami iteratora i o (1) przestrzenią.

Iteratory stylu Java nie mają możliwości samodzielnego przechowywania pozycji. Będziesz albo

  • lose o (1) space, using (for example) an tablica rozmiaru M do przechowywania historii podczas iteracji
  • będzie musiał przejść listę N razy, co O (N^2+N*m) CZAS
  • lub użyć konkretnego typu tablicy z funkcją getat member, tracąc generyczność i możliwość użycia połączonych typów kontenerów list.

Ponieważ w tym przykładzie użyto tylko mechaniki iteracji forward, mogłem zamienić listę z bez problemów . Ma to kluczowe znaczenie dla tworzenia algorytmów generycznych, takich jak wyszukiwanie, opóźniona inicjalizacja i ocena, sortowanie itp.

Niemożność zachowania stanu najbardziej odpowiada iteratorowi wejściowemu C++ STL, na którym zbudowano bardzo mało algorytmów.

 11
Author: Aaron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 20:05:11

Wskaźnik do elementu tablicy jest rzeczywiście iteratorem do tablicy.

Jak mówisz, w Javie iterator ma większą wiedzę na temat bazowego kontenera niż w C++. Iteratory C++ są ogólne, a para iteratorów może oznaczać dowolny zakres: może to być podzakres kontenera, zakres nad wieloma kontenerami (zobacz http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdf lub http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html ) lub nawet zakres liczb (patrz http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/counting_iterator.html )

Kategorie iteratora określają, co możesz, a czego nie możesz zrobić z danym iteratorem.

 7
Author: Anthony Williams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 12:23:54

Dla mnie zasadnicza różnica polega na tym, że Iteratory Java wskazują na elementy, podczas gdy Iteratory C++ STL wskazują na elementy.

 3
Author: Douglas Leeder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 15:01:01

Iteratory C++ są uogólnieniem pojęcia wskaźnika; sprawiają, że można je zastosować do szerszego zakresu sytuacji. Oznacza to, że mogą być używane do takich rzeczy, jak definiowanie dowolnych zakresów.

Iteratory Javy są stosunkowo głupimi enumeratorami (choć nie tak źle jak C#; przynajmniej Java ma ListIterator i może być używana do mutacji kolekcji).

 2
Author: DrPizza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-12 10:48:59

Iteratory są równoważne wskaźnikom tylko w trywialnym przypadku iteracji nad zawartością tablicy w sekwencji. Iterator może dostarczać obiekty z dowolnej liczby innych źródeł: z bazy danych, z pliku, z sieci, z innych obliczeń itp.

 1
Author: Marcus Downing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 12:20:26

Iteratory biblioteki C++ (część wcześniej znana jako STL) są zaprojektowane tak, aby były kompatybilne ze wskaźnikami. Java, bez arytmetyki wskaźników, miała swobodę bycia bardziej przyjazną programiście.

W C++ kończy się konieczność użycia pary iteratorów. W Javie używasz iteratora lub kolekcji. Iteratory mają być spoiwem między algorytmem a strukturą danych. Kod napisany dla 1.5+ rzadko wymaga iteratorów, chyba że implementuje określony algorytm lub dane struktury (czego różna większość programistów nie musi robić). Jak Java idzie do dynamicznego polimorfizmu podzbiory i tym podobne są znacznie łatwiejsze w obsłudze.

 1
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 12:41:53

Istnieje wiele dobrych odpowiedzi na temat różnic, ale czułem, że to, co najbardziej denerwuje mnie z iteratorami Javy, nie zostało podkreślone-nie można odczytać bieżącej wartości wiele razy. Jest to bardzo przydatne w wielu scenariuszach, szczególnie podczas łączenia iteratorów.

W c++, masz metodę, aby przyspieszyć iterator i odczytać bieżącą wartość. Odczytanie jej wartości nie przyspiesza iteracji, więc można ją odczytać wiele razy. Nie jest to możliwe w przypadku Javy Iteratory i kończę tworząc opakowania, które to robią.

Uwaga na marginesie: jednym z łatwych sposobów na stworzenie wrappera jest użycie istniejącego -- PeekingIterator z Guava.

 1
Author: Neo M Hacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 21:18:40