2011-07-30 32 views
7

Czy istnieje możliwość usunięcia elementu z std::list, jeśli tylko iterator wskazuje element, który chcesz usunąć? Mam wiele funkcji, które biorą udział w iteratorach do wypisywania elementów, i byłoby ogromnym niedogodnością, gdyby każdy z nich musiał przekazać posiadany numer list.Usuwanie elementu z listy za pomocą iteratora

+1

Należy zauważyć, że używanie iteratora w ten sposób jest sprzeczne z jego użyciem jako wzorca projektowego, ale nie oznacza to, że nie jest to właściwe postępowanie w wielu sytuacjach (np. Przeglądanie elementów zestawu.) – Jeremy

+0

http: // stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – nielsj

+0

@Jeremy: właściwie to nie jest użycie iteratora jako wzorca projektowego. Ma jednak słabą semantykę w odniesieniu do unieważniania iteratora. W wielu kontenerach usunięcie elementu powoduje unieważnienie wszystkich iteratorów, w tym tego, którego obecnie używasz do iterowania elementów. –

Odpowiedz

3

Edit:

cant z jednym iteracyjnej.

Jeśli masz iteratory początku/końca, możesz użyć algorytmu std::remove, aby przesunąć wszystkie elementy, które chcesz wymazać do końca, i usunąć je w późniejszym czasie.

Jeśli nie, lub powyższe nie jest możliwe z bieżącego projektu, polecam zmianę funkcji, aby podjąć std::pair<std::list<T>, std::list<T>::iterator> lub coś w tym stylu.

+2

Ale wymaga to również listy. – Dani

+1

Funkcja 'std :: remove()' nie * usuwa elementów z kontenera *, ponieważ po prostu nie może. Sprawdź [idź usuń-usuń] (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove). –

+0

@ André - To jest to, co powiedziałem.Użyj go, aby przenieść je na koniec _i usuń je w późniejszym terminie_ – Node

0

Nie, nie jest to możliwe. Jak sama nazwa wskazuje, zadaniem iteratora jest iteracja nad elementami sekwencji. Sprawdź podsumowanie projektu iteratora w bibliotece standardowej C++ pod numerem SGI page on iterators.

+0

Ponieważ 'list' jest podwójnie połączoną listą, czy nie mógłbyś napisać funkcji do manipulowania wskaźnikami' next' i 'previous', aby usunąć element? A może byłoby naprawdę źle? Czy może po prostu członkowie są prywatni? –

+0

@Seth: tak, jest to technicznie możliwe. Na przykład w Javie iteratory mają metodę [remove method] (http://download.oracle.com/javase/1.4.2/docs/api/java/util/Iterator.html#remove()). Jednak nie jest to częścią projektu iteratora C++. Sądzę, że standardowa komisja preferowała jednolitość z innymi pojemnikami. –

+0

@Seth: można to zrobić dla konkretnej wersji biblioteki określonego dostawcy. Oznacza to jednak wiele niestandardowych (i zdecydowanie nieprzenośnych) kodów. Co więcej, członkowie są prawdopodobnie prywatni. –

3

Nie, nie możesz. Iteratory są lekkimi obiektami wzorowanymi na wskaźnikach i nie zawierają odniesienia do kontenera, do którego się odnoszą. (Chociaż niektóre implementacje robią to wewnętrznie w trybie debugowania.)

Tak jak nie można "usunąć" obiektu z tablicy, gdy wszystko, co mamy, jest wskaźnikiem do tablicy, nie można usunąć obiektu z pojemnika bez dostęp do kontenera.

-1

Możesz to zrobić ręcznie. iterator odsłania _M_node jako bieżący węzeł. można zrobić coś takiego:

itr._M_node->_M_prev->_M_next = itr._M_node._M_next; 
+2

Dzieje się tak tylko w przypadku konkretnego iteratora w konkretnym kontenerze w konkretnych wersjach konkretnej implementacji, jest to szczegół implementacji, a nawet można go wyłączyć, używając odpowiedniego tokena preprocesora. Może również zepsuć wewnętrzne elementy kontenera, które musisz znać, aby to zrobić. – sbi

+0

Nie powiedziałem, że jest on czysty. twoje ostrzeżenie jest poprawne. – Dani

+1

Nie wspominając już o tym, że nie zaktualizowałeś wskaźnika '_M_prev' z' _M_next' (ponieważ jest to lista dlinkowa). O tym właśnie myślałem, ale ten kod musi również działać z różnymi wersjami/kompilatorami. –

1

Podczas gdy inni wspomnieli, że nie możesz tego zrobić, myślę, że mogę zaoferować, dlaczego.

Uważam, że konkretną przyczyną techniczną (a nie powodem projektowania) jest to, że listy utrzymują się na pewnym poziomie, na przykład śledzenie wielkości, które wymagają przepuszczenia określonych czynności, aby umożliwić utrzymanie.

Z tego powodu każdy hack, który może być oferowany, prawdopodobnie zawiedzie.

+0

To dobra myśl, choć wygląda na to, że możesz sprawić, żeby iteratory powiedziały swojej liście rodziców, że same się usuwają. –

Powiązane problemy