splice() для std::list и инвалидации итератора

Форма с тремя аргументами list::splice() перемещает один элемент из одного списка в другой. В документации SGI прямо указано, что все итераторы, включая один, указывающий на перемещаемый элемент, остается действительным. документация Roguewave ничего не говорит о свойствах аннулирования итератора методов splice(), тогда как стандарт C++ прямо указывает что он делает недействительными все итераторы и ссылки на объединяемый элемент.

splicing() на практике работает так, как определено SGI, но я получаю ошибку утверждения (разыменование недопустимого итератора) в отладочных/безопасных версиях SCL реализации Microsoft STL (что строго соответствует букве стандарта).

Теперь я использую список именно потому, что хочу перемещать элемент между списками, сохраняя при этом действительность указывающего на него итератора. Стандарт внес крайне бесполезное изменение в исходную спецификацию SGI.

Как я могу обойти эту проблему? Или я должен просто быть прагматичным и засунуть голову в песок (поскольку сращивание не делает итераторы недействительными на практике - даже в реализации MS, когда отладка итератора отключена).


person zvrba    schedule 27.09.2008    source источник
comment
Отличный вопрос. Какое было последнее слово?   -  person Alexandre C.    schedule 04.08.2011
comment
Стандарт глупый, но правильный. Не используйте склейку в программах, соответствующих стандартам. Возможно, C++1x изменил ситуацию; Я не проверял.   -  person zvrba    schedule 05.08.2011
comment
Только что проверил, меняется. Сохраненная формулировка относится к дефекту 250 LWG: старые итераторы допустимы и ведут себя так, как будто они указывают на новый контейнер.   -  person Alexandre C.    schedule 05.08.2011


Ответы (3)



Проблема в том, что если итератор по-прежнему указывает на перемещенный элемент, значит, "конечный" итератор, ранее связанный с "перемещенным" итератором, изменился. Если вы не напишете какой-нибудь сложный цикл, это на самом деле плохо, особенно потому, что другим разработчикам будет труднее понять.

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

person Kevin    schedule 27.09.2008
comment
Зависит от того, держит ли он итераторы для доступа к элементам, не теряя возможности манипулирования списком, или же он в настоящее время перебирает список, и в этом случае ему действительно придется быть осторожным. - person Fruny; 27.09.2008

У меня есть массив списков (классы эквивалентности элементов), и я использую объединение для перемещения элементов между списками. У меня есть дополнительный массив итераторов, который дает мне прямой доступ к любому элементу в любом из списков и перемещение его в другой список. Ни один из списков не просматривается и не модифицируется одновременно. Я мог бы повторно инициализировать итератор элемента после объединения, но это довольно некрасиво. Думаю, я пока так и сделаю.

person zvrba    schedule 27.09.2008