Удаление элементов из списка std::list в цикле |
Здравствуйте, гость ( Вход | Регистрация )
Удаление элементов из списка std::list в цикле |
Влад |
19.10.2012, 12:10
Сообщение
#21
|
Участник Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: 8 |
В общем, в результате изучения Стандарта (D_K спасибо за ссылку на 24.4.1) у меня сложилось устойчивое впечатление, что "падающий" код - это следствие косяков конкретных реализаций. Стандарт устанавливает только требования к интерфейсу reverse_iterator, но ничего не говорит о его внутреннем устройстве; это абсолютно нормально. Равным образом, в Стандарте нет требования (requirement) о том, что reverse_iterator обязательно должен содержать iterator, указывающий на предыдущий элемент, - тот самый, который становится невалидным в нашем коде, и основывать свою работу на нем. Таким образом, это остается на усмотрение разработчиков реализации....
К сожалению, в большинстве случаев мы сильно ограничены в выборе реализаций STL. Теоретически, код из поста #10 не противоречит Стандарту и абсолютно валиден (и это тот же самый совет Мейерса #28, только записанный немного подробнее). Однако в конкретных реализациях мы видим, что он не работает. Увы. |
|
|
D_K |
19.10.2012, 15:06
Сообщение
#22
|
Студент Группа: Участник Сообщений: 20 Регистрация: 20.5.2009 Пользователь №: 761 Спасибо сказали: 3 раз(а) Репутация: 1 |
Влад, а как же
Цитата(24.4.1.1)
Ну и дальше все операции через current расписаны... |
|
|
Влад |
19.10.2012, 15:35
Сообщение
#23
|
Участник Группа: Участник Сообщений: 146 Регистрация: 20.3.2009 Из: Санкт-Петербург Пользователь №: 627 Спасибо сказали: 46 раз(а) Репутация: 8 |
Тут бы я не согласился. Вот этот самый current - исключительно деталь внутренней реализации реверсивного итератора. И, в то же время, Стандарт иллюстрирует effects через current, но не дает никаких указаний о содержимом current после операций типа erase/insert и о моментах его обновления. В то же время, в Ст.23.2.2.3 (напоминает "Матф. 18:13", не правда ли? :-) ) явно указывает:
Effects: Invalidates only the iterators and references to the erased elements. Учтем, что в этот момент reverse_iterator не указывает на erased element, а о его внутреннем устройстве (в том числе, о protected членах) я, как "внешний" пользователь, вообще ничего знать не обязан. :-) А нежелательные эффекты возникают из-за излишне прямолинейного копирования иллюстративного кода в Стандарте - в программный код. Т.е., я имею в виду, что код должен следовать требованиям Стандарта по принципу "включая, но не ограничиваясь". А вот это, видимо, выполняется не во всех реализациях. Дискуссия по этому вопросу и возражения приветствуются! |
|
|
D_K |
19.10.2012, 17:10
Сообщение
#24
|
Студент Группа: Участник Сообщений: 20 Регистрация: 20.5.2009 Пользователь №: 761 Спасибо сказали: 3 раз(а) Репутация: 1 |
ИМХО. Стандарт, в первую очередь, предназначен для реализаций языка.
И по-моему, вот из этого: Цитата explicit reverse_iterator(Iterator x); Effects: Initializes current with x. ... Iterator base() const; Returns: current ... reference operator*() const; Effects: Iterator tmp = current; return *--tmp; ... pointer operator->() const; Effects: return &(operator*()); ... reverse_iterator& operator++(); Effects: --current; Returns: *this ... reverse_iterator operator--(int); Effects: reverse_iterator tmp = *this; --current; return tmp; следует, что итератор станет невалидным... Кроме того, Iteratir current - это protected-член. Соответственно, это часть интерфейса наследования. |
|
|
Iron Bug |
19.10.2012, 19:56
Сообщение
#25
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
если вкратце, то erase превращает итератор в так называемое singular value. можно представить его как аналог NULL для указателей. это значение, не принадлежащее ни одному контейнеру. поэтому после erase итератор становится невалиден и постфиксная операция iter++ будет невалидна. а вот если взять префиксный плюс (++iter) прямо внутри вызова erase, то всё будет ok, потому что сначала итератор изменится, а его "старое" значение будет скопировано, копия будет использована в erase и перейдёт в singular value.
Сообщение отредактировал Iron Bug - 19.10.2012, 19:58 |
|
|
D_K |
20.10.2012, 15:54
Сообщение
#26
|
Студент Группа: Участник Сообщений: 20 Регистрация: 20.5.2009 Пользователь №: 761 Спасибо сказали: 3 раз(а) Репутация: 1 |
Iron Bug, так не об этом речь. reverse_iterator'ы обсуждаем.
|
|
|
Iron Bug |
20.10.2012, 19:02
Сообщение
#27
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
Iron Bug, так не об этом речь. reverse_iterator'ы обсуждаем. именно об этом. реверс-итератор ничем принципиально не отличается от обычного итератора и у него при вызове erase точно также будут работать префиксные плюсы и не будут работать постфиксные. Сообщение отредактировал Iron Bug - 20.10.2012, 19:03 |
|
|
D_K |
21.10.2012, 23:41
Сообщение
#28
|
Студент Группа: Участник Сообщений: 20 Регистрация: 20.5.2009 Пользователь №: 761 Спасибо сказали: 3 раз(а) Репутация: 1 |
Iron Bug, как вы собираетесь делать erase с reverse_iterator'ом? Это возможно только через метод base(), возвращающий обычный итератор.
|
|
|
Iron Bug |
22.10.2012, 7:15
Сообщение
#29
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
Iron Bug, как вы собираетесь делать erase с reverse_iterator'ом? Это возможно только через метод base(), возвращающий обычный итератор. и чем же он плох? просто erase сам по себе не принимает обратный итератор. но сам итератор от этого ничуть не страдает. вот обычный метод, который работает, удаляя элементы в обратном порядке.
|
|
|
D_K |
22.10.2012, 11:12
Сообщение
#30
|
Студент Группа: Участник Сообщений: 20 Регистрация: 20.5.2009 Пользователь №: 761 Спасибо сказали: 3 раз(а) Репутация: 1 |
Неясно, к чему это.
|
|
|
Текстовая версия | Сейчас: 29.3.2024, 8:14 |