Программирование >>  Операторы преобразования типа 

1 ... 33 34 35 [ 36 ] 37 38 39 ... 239


number of removed elements: 2 654211245656

Если вы предпочитаете удалять элементы одной командой, воспользуйтесь следзтощей конструкцией:

coll .erase (reinove(coll .beginO .coll ,end(). 3).

coll.endO):

Почему сами алгоритмы не вызывают функцию erase()? Ответ на этот вопрос снова напоминает о том, что гибкость STL не дается даром. STL отделяет структуры данных от алгоритмов, используя итераторы в качестве интерфейсов. Но как отмечалось выше, итератор является абстракцией для представления позиции в контейнере. В общем случае итератор просто не знает свой контейнер. Таким образом, алгоритм, работающий с элементами контейнера через итератор, не может вызывать функции контейнера.

Подобная архитектура имеет важные последствия, поскольку благодаря ей алгоритмы работают с абстрактными интервалами, а не только со всеми элементами контейнера . Например, интервал может состоять из подмножества элементов коллекции. Более того, некоторые контейнеры (например, обычные массивы) не поддерживают функцию erase(). Следовательно, стремление сохранить максимальную гибкость алгоритмов не позволяет требовать, чтобы итераторы располагали информацией о своих контейнерах.

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

Модифицирующие алгоритмы и ассоциативные контейнеры

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

К сожалению, в некоторых системах обработка ошибок реализована крайне плохо. Вы понимаете, что в программе что-то явно не так, но причины происходящего остаются неизвестными. Некоторые компиляторы даже не отображают фрагмент исходного текста, а котором обнаружена ошибка. Вероятно, в будущем ситуация изменится.



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

Возникает вопрос: как же удалить элементы из ассоциативного контейнера? Ответ прост: воспользуйтесь собственными функциями контейнера! В каждом -ассоциативном контейнере предусмотрены функции удаления элементов. Напри- мер, элементы можно удалить функцией erase():

stl/removes.срр Iinclude <iostream> Iinclude <set> Iinclude <algorithm> using namespace std:

int mainO {

set<int> coll;

Вставка элементов со значениями от 1 до 9 for (int 1=1: i<=9; ++i) { coll.insert(i);

Вывод всех элементов коллекции copy (coll .beginO. coll.endO.

ostream iterator<int>(cout, )); cout endl;

/* Удаление всех элементов со значением 3

* - алгоритм removeO не работает

* - используем функцию eraseO */

int num = coll.erase(3);

Вывод количества удаленных элементов

cout number of removed elements: num endl;

Вывод всех элементов модифицированной коллекции сору (col 1 .begin(). coll.endO.

ostream iterator<int>(cout. )): cout endl;

Контейнеры поддерживают несколько версий функции erase(). Только та версия, единственным аргументом которой является значение удаляемого элемента (или элементов), возвращает количество удаленных элементов (см. с. 248). Разумеется, если дубликаты в коллекции запрещены (как в мнолсествах н отображениях), возвращаемое значение функции может быть равно только О или 1.



Результат работы программы выглядит так:

1 2 3 4 5 6 7 8 9

number of removed elements: 1

12 4 5 6 7 8 9

Алгоритмы и функции классов

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

Хорошим примером служит вызов алгоритма remove() для элементов списка. Алгоритм не зпает, что он работает со списком, поэтому он делает то же, что в любом другом контейнере, - переупорядочивает элсхменты, изменяя их значения. Например, при удалении первого элемента каждому элементу присваивается значение элемента, следующего после пего. Такой подход игнорирует основное достоинство списков - возможность выполнения вставки, перемещения и удаления элементов посредством модификации ссылок, а не элементов.

Для повышения эффективности операций в списках определены специальные функции для всех модифицирующих алгоритмов. Всегда используйте их вместо алгоритмов. Более того, как показывает следующий пример, эти функции действительно исключают удаляемые элементы:

stl/remove4.cpp Iinclude <1ostream> Iinclude <list> Iinclude <algorithm> using namespace std:

int main() {

11st<1nt> col 1:

Вставка элементов со значениями от 6 до 1 и от 1 до 6 for (int 1=1; i<=6; ++i) {

coll.push front(1);

coll,push back(i):

Удаление всех элементов со значением 3 - неэффективно

coll.erase (remove(coll.beginC),col1,end(). 3)-

coll .endO):

Удаление всех элементов со значением 4 - эффективно coll.remove (4):



1 ... 33 34 35 [ 36 ] 37 38 39 ... 239

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика