Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

Эффективное использование STL. Библиотека программиста - Мейерс С.

Мейерс С. Эффективное использование STL. Библиотека программиста — Спб.: Питер , 2002. — 224 c.
ISBN 5-94723-382-7
Скачать (прямая ссылка): effektivnoeispolzovaniestlbibliote2002.djvu
Предыдущая << 1 .. 62 63 64 65 66 67 < 68 > 69 70 71 72 73 74 .. 114 >> Следующая

v.beginQ v.endQ
i_____________к
1 2 3 5 7 8 9 ? ? ?
T
newEnd
Вопросительными знаками отмечены значения элементов, "концептуально"
удаленных из v, но продолжающих благополучно существовать.
Раз "оставшиеся" элементы v находятся между v.beginO и newEnd, было бы
логично предположить, что "удаленные" элементы будут находиться между
newEnd и v.endO. Но это не так\ Присутствие "удаленных" элементов в v
вообще не
Совет 32 133
гарантировано. Алгоритм remove не изменяет порядок элементов в интервале
так, чтобы "удаленные" элементы сгруппировались в конце - он перемещает
"остающиеся" элементы в начало. Хотя в Стандарте такое требование
отсутствует, элементы за новым логическим концом интервала обычно
сохраняют свои старые значения. Во всех известных мне реализациях после
вызова remove вектор v выглядит так:
v.beginQ v.end()
1 2 3 5 7 8 9 8 9 99
newEnd
Как видите, два значения "99", ранее существовавших в v, исчезли, а одно
осталось. В общем случае после вызова remove элементы, удаленные из
интервала, могут остаться в нем, а могут исчезнуть. Многие программисты
находят это странным, но почему? Вы просите remove убрать некоторые
элементы, алгоритм выполняет вашу просьбу. Вы же не просили разместить
удаленные значения в особом месте для последующего использования... Так в
чем проблема? (Чтобы предотвратить потерю значений, вместо remove лучше
воспользоваться алгоритмом parti ti on, описанным в совете 31.)
На первый взгляд поведение remove выглядит довольно странно, но оно
является прямым следствием принципа работы алгоритма. Во внутренней
реализации remove перебирает содержимое интервала и перезаписывает
"удаляемые" значения "сохраняемыми". Перезапись реализуется посредством
присваивания.
Алгоритм remove можно рассматривать как разновидность уплотнения, при
этом удаляемые значения играют роль "пустот", заполняемых в процессе
уплотнения. Опишем, что происходит с вектором v из нашего примера.
1. Алгоритм remove анализирует v[0], видит, что данный элемент не
должен удаляться, и перемещается к v[l]. То же самое происходит с
элементами v[l] и v[2].
2. Алгоритм определяет, что элемент v[3] подлежит удалению, запоминает
этот факт и переходит к v[4]. Фактически v[3] рассматривается как "дыра",
подлежащая заполнению.
3. Значение v[4] необходимо сохранить, поэтому алгоритм присваивает
v[4] элементу v[3], запоминает, что v[4] подлежит перезаписи, и переходит
к v[5]. Если продолжить аналогию с уплотнением, элемент v[3]
"заполняется" значением v[4], а на месте v[4] образуется новая "дыра".
4. Элемент v[5] исключается, поэтому алгоритм игнорирует его и
переходит к v[6]. При этом он продолжает помнить, что на месте v[4]
остается "дыра", которую нужно заполнить.
5. Элемент v[6] сохраняется, поэтому алгоритм присваивает v[6]
элементу v[4], вспоминает, что следующая "дыра" находится на месте v[5],
и переходит к v[7].
134 Глава 5 • Алгоритмы
6. Аналогичным образом анализируются элементы v[7], v[8] и v[9].
Значение v[7] присваивается элементу v[5], а значение v[8] присваивается
элементу v[6]. Элемент v[9] игнорируется, поскольку находящееся в нем
значение подлежит удалению.
7. Алгоритм возвращает итератор для элемента, следующего за последним
"оставшимся". В данном примере это элемент v[7].
Перемещения элементов в векторе v выглядят следующим образом:
1 2 3 99 5 99 7 8 9 99
Как объясняется в совете 33, факт перезаписи некоторых удаляемых значений
имеет важные последствия в том случае, если эти значения являются
указателями. Но в контексте данного совета достаточно понимать, что
remove не удаляет элементы из контейнера, поскольку в принципе не может
этого сделать. Элементы могут удаляться лишь функциями контейнера, отсюда
следует и главное правило настоящего совета: чтобы удалить элементы из
контейнера, вызовите erase после remove.
Элементы, подлежащие фактическому удалению, определить нетрудно - это все
элементы исходного интервала, начиная с нового "логического конца"
интервала и завершая его "физическим" концом. Чтобы уничтожить все эти
элементы, достаточно вызвать интервальную форму erase (см. совет 5) и
передать ей эти два итератора. Поскольку сам алгоритм remove возвращает
итератор для нового логического конца массива, задача решается
прямолинейно:
vector<int> v; //См. ранее
v.erase(renrave(v.begin().v.end(),99),v.end()): // Фактическое удаление
// элементов со значением 99
cout " v.sizeO: // Теперь выводится 7
Передача в первом аргументе интервальной формы erase возвращаемого
значения remove используется так часто, что рассматривается как
стандартная конструкция. Remove и erase настолько тесно связаны, что они
были объединены в функцию remove контейнера 1 i st. Это единственная
функция STL с именем remove, которая производит фактическое удаление
элементов из контейнера:
list<int> li; // Создать список
// Заполнить данными
li.remove(99); // Удалить все элементы со значением 99.
// Команда производит фактическое удаление // элементов из контейнера,
Предыдущая << 1 .. 62 63 64 65 66 67 < 68 > 69 70 71 72 73 74 .. 114 >> Следующая