Изменение контейнера при использовании посетителя - PullRequest
2 голосов
/ 15 апреля 2010

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

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

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

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

С уважением, Florian

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

Ответы [ 3 ]

0 голосов
/ 15 апреля 2010

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

0 голосов
/ 16 апреля 2010

В этих случаях, если копирование моего контейнера не дорого, я просто копирую его и выполняю итерацию на копии. В исходном контейнере хранятся объекты с помощью shared_ptr, а в копии - слабый_ptr.

0 голосов
/ 15 апреля 2010

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

...