2010-04-15 4 views
2

Я реализовал шаблон посетителя в C++ с использованием STL-подобного итератора для хранения текущего положения Visitor в контейнере. Теперь я хотел бы изменить контейнер, пока я перебираю его, и мне особенно интересно удалить элементы из контейнера, даже тот, который я сейчас посещаю.Изменение контейнера при использовании посетителя

Теперь очевидно, что это приведет к аннулированию внутреннего итератора посетителей, поскольку это указывает именно на этот элемент. В настоящее время я храню список всех итераторов в контейнере и обновляю их, как только что-либо добавляется или удаляется из списка. Таким образом, это похоже на шаблон Observer, применяемый к итератору (как Observer) и списку (как Observable).

В качестве альтернативы, я считал, что методы visitor() возвращают посетителю какой-либо намек на то, что происходит с текущим элементом и как продолжить повторение, но это тоже не похоже на такую ​​хорошую идею, потому что посещение() реализация не должна заботиться о поиске следующего элемента.

Итак, мой вопрос: что является лучшим способом заставить посетителя работать, даже когда элементы добавляются в контейнер или удаляются из него.

С уважением, Флориан

Update: Там один посетитель работает над контейнером, а внутри метода посещения() любое количество дополнительных итераторы могут быть использованы в том же контейнере. Я хочу, чтобы посетитель продолжал работу с остальными элементами в контейнере, даже после того, как мы вернулись с вызова для посещения(), в котором один из элементов в контейнере был удален.

+0

Я немного смущен вашим описанием. У вас есть несколько посетителей, проходящих через контейнер, которые необходимо обновить, когда какой-либо посетитель внесет изменения? Вы хотите, чтобы посетитель повторно подтвердил свою позицию, когда есть какие-либо изменения, внесенные в контейнер - даже лицами, не являющимися посетителями? Или это случай, когда у вас только один посетитель за раз, и что упомянутый посетитель должен всегда оставлять себя с действительным итератором после посещения элемента в контейнере? –

+0

Я тоже смущен. Я думаю, что большее объяснение (или код) о том, как вы реализовали посетителя в контейнере STL, может помочь здесь. Что он принимает, объект и итератор? Кто меняет итераторы, чтобы посетил следующий элемент? –

ответ

0

При мутации контейнера во время обхода итераторы в лучшем случае опасны. Безопаснее использовать индекс и идти назад.

+3

При использовании контейнера последовательности итераторы могут использоваться безопасно даже при мутировании контейнера. Вам просто нужно заменить итератор, который вы использовали с итератором, возвращаемым методом вставки или стирания. –

+0

Вы имеете в виду, как 'it = container.erase (it);'? Это звучит достаточно хорошо для меня, но как я объединил его с шаблоном посетителя? – Florian

0

Я думаю, что ваша (первая) реализация довольно хороша, если не так много итераторов и операций удаления. Если бы это было так, я бы использовал отметку и развернул, как алгоритм, подобный Эдди. Кроме того, я думаю, что последнее проще и, следовательно, менее подвержено ошибкам. Не забудьте пропустить узлы, отмеченные для удаления. С другой стороны, если есть случаи, кроме «удалить», где ваши итераторы должны быть обновлены, придерживайтесь своей текущей реализации.

0

В этих случаях, если копирование моего контейнера не дорого, я просто копирую его и повторяю на копии. Исходный контейнер хранит объекты shared_ptr, тогда как копия просто содержит weak_ptr.

Смежные вопросы