Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> удалить элемент std::set во время его обхода 
V
    Опции темы
semibug
Дата 7.11.2011, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет




С stl знаком поверхностно, судя по тестам вроде все работает как и задумано, но нет ли здесь подводных камней?

Код


class Foo;

std::set<Foo*> s;

//...

for ( std::set<Foo*>::iterator it = s.begin(); it != s.end(); it++ )
{
  if ( "something" )
    s.erase( *it );
}


Можно ли таким образом удалять элементы множества во время его обхода?
На что будет указывать итератор после выполнения erase? Не будет ли пропуска следующего за удалённым элемента после очередного it++?
Сам объект класс Foo, указатель на который был удален из множества с помощью erase остается в памяти?



PM   Вверх
bsa
Дата 7.11.2011, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Во-первых, у тебя ошибка. ты в set::erase передаешь разыменованный указатель. Что является принципиальной ошибкой (т.е. компилироваться не будет).
Во-вторых:
Цитата(http://www.sgi.com/tech/stl/set.html)
Erasing an element from a set also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.
Это значит, что ты должен писать цикл следующим образом:
Код
for ( std::set<Foo*>::iterator it = s.begin(), e = s.end(); it != e;)
{
  if ( "something" )
    s.erase( it++ );
  else
    ++it;
}


Это сообщение отредактировал(а) bsa - 7.11.2011, 11:30
PM   Вверх
azesmcar
Дата 7.11.2011, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



http://stackoverflow.com/questions/2874441...ng-new-solution

Добавлено через 31 секунду
опередили smile
PM   Вверх
semibug
Дата 7.11.2011, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



Цитата(bsa @  7.11.2011,  11:29 Найти цитируемый пост)
Во-первых, у тебя ошибка. ты в set::erase передаешь разыменованный указатель. Что является принципиальной ошибкой (т.е. компилироваться не будет).

Что тоже странно, т.к. собиралось без ошибок. Сейчас убрал звездочку, тоже компилится.
liveworkspace

а на счет
Код

for ( std::set<Foo*>::iterator it = s.begin(), e = s.end(); it != e;)
{
  if ( "something" )
    s.erase( it++ );
  else
    ++it;
}

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


PM   Вверх
bsa
Дата 7.11.2011, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



semibug, кстати, а зачем нужен set с указателями? Ты, надеюсь, контролируешь утечки памяти, которые могут возникнуть после erase?
PM   Вверх
semibug
Дата 7.11.2011, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



bsa, использую множество как хранилище объектов. Перед erase сначала делаю delete (*it), затем .erase(it).
Так понял, вопрос наводящий - использовать вместо указателей сами объекты?




PM   Вверх
bsa
Дата 7.11.2011, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(semibug @  7.11.2011,  13:56 Найти цитируемый пост)
Так понял, вопрос наводящий - использовать вместо указателей сами объекты?

можно и сами объекты, можно и vector/deque/list... Просто я лично не вижу никакого смысла в использовании set для указателей без специального сравнивателя. set тратит много ресурсов на поддержание контейнера в отсортированном виде. Если контейнер хранит указатели, то порядок сортировки можно считать отсутствующим. Так как размер хранимых объектов (указатель) достаточно мал, можно использовать вектор (если массив на на млн. элементов или удаление/вставка в основном в конец), дек (если много удалений/вставок в начало/середину) или list (если вставка/удаление в основном в середину)...
PM   Вверх
semibug
Дата 7.11.2011, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



bsa, спасибо, попробую list, не понял на счет "дек", если это deque, то он вроде не позволяет вставлять в середину?

PM   Вверх
bsa
Дата 7.11.2011, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(semibug @  7.11.2011,  16:54 Найти цитируемый пост)
если это deque, то он вроде не позволяет вставлять в середину?

Давно? Он позволяет, только это не быстрее, чем у вектора. Зато в начало/конец добавляет быстро.
Недостаток списка - только последовательный перебор элементов и сильный оверхэд по памяти (+2 указателя к каждому элементу) для маленьких объектов. Со списком есть смысл использовать не указатели, а сами объекты, если, конечно, они поддерживают семантику копирования...
PM   Вверх
semibug
Дата 7.11.2011, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



bsa, спасибо за просветление, предположил из названия (deque) что можно оперировать только с концами. А тут и у vector оказался метод insert, что также мне в новинку.


PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0784 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.