- •4.6. Иерархия итераторов stl: эффективная комбинация алгоритмов и контейнеров
 - •4.7. Итераторы вставки
 - •4.8. Еще раз о входе и выходе: потоковые итераторы
 - •4.9. Спецификация категорий итераторов, требуемых алгоритмами stl
 - •4.10. Разработка обобщенных алгоритмов
 - •4.11. Почему некоторые алгоритмы требуют более мощные итераторы
 - •4.12. Выбор правильного алгоритма
 - •4.13. Константные и изменяемые итераторы
 - •4.14. Категории итераторов, предоставляемые контейнерами stl
 
4.14. Категории итераторов, предоставляемые контейнерами stl
В табл. 4.1 показаны категории каждого типа итераторов, которые предоставляют контейнеры STL. Обратите внимание, что для set и multiset как iterator, так и const_iterator представляют собой константные двунаправленные итераторы — т.е. фактически это один и тот же тип. Причина этого в том, что единственный разрешенный метод изменения ключа— это его удаление (при помощи функции-члена erase), а затем вставка другого ключа (посредством функции-члена insert). Если бы итераторы множеств и мультимножеств были
неконстантными, то было бы можно модифицировать ключи без участия функций-членов erase и insert, и такое изменение могло бы привести к нарушению свойства размещения элементов в отсортированном порядке. Приведенный ниже пример иллюстрирует сказанное:
#include <set>
set<int> s;
s.insert(3);
s.insert(5);
s.insert(7);
set<int> :: iterator i = s.begin();
*i = 4; // Неверно
Эта программа не будет компилироваться, поскольку i представляет собой константный итератор, а элементы не могут быть изменены посредством константного итератора. Вместо этого мы должны записать
s.erase(i);
s.insert(4);
Аналогичное ограничение действует и для отображений и мультиотображений. Объект типа map<Кеу, Т> хранит значения типа pair<const Key, T>. Ключ данной пары не может быть модифицирован непосредственно, но можно модифицировать значение типа Т. Эта идея иллюстрируется приведенным ниже примером:
#include <map>
typedef multimap<int, double> multimap_1;
multimap_1 m;
m.insert(pair<const int, double>(3, 4.1));
multimap_1::iterator i = m.begin();
*i = pair<const int, double>(3, 5.1); // Неверно
Это неверный метод изменения значений, и компилироваться такой код не будет.
Корректный метод состоит в удалении значения, на которое указывает i, и вставке новой пары:
m.erase(i);
m.insert(pair<const int, double>(3, 5.1));
Можно также записать
i->second = 5.1;
поскольку значения, связанные с ключами, могут быть изменены с помощью неконстантного итератора. Такой метод предпочтительнее, поскольку он эффективнее, чем erase и insert. Однако он не будет работать, если объявить i как multimap_1: :const_iterator, поскольку константные итераторы не допускают изменения значений, на которые они указывают.
Таблица 4.1. Категории итераторов, предоставляемые контейнерами STL
Контейнер  | 
		Итератор  | 
		Категория итератора  | 
	
Т а[п]  | 
		T*  | 
		Изменяемый с произвольным доступом  | 
	
Т а[п]  | 
		const T*  | 
		Константный с произвольным доступом  | 
	
vector<T>  | 
		vector<T>::iterator  | 
		Изменяемый с произвольным доступом  | 
	
vector<T>  | 
		vector<T>::const_iterator  | 
		Константный с произвольным доступом  | 
	
deque<T>  | 
		deque<T>::iterator  | 
		Изменяемый с произвольным доступом  | 
	
deque<T>  | 
		deque<T>::const_iterator  | 
		Константный с произвольным доступом  | 
	
list<T>  | 
		list<T>::iterator  | 
		Изменяемый двунаправленный  | 
	
list<T>  | 
		list<T>::const_iterator  | 
		Константный двунаправленный  | 
	
set<T>  | 
		set<T>::iterator  | 
		Изменяемый двунаправленный  | 
	
set<T>  | 
		set<T>::const_iterator  | 
		Константный двунаправленный  | 
	
multiset<T>  | 
		multiset<T>::iterator  | 
		Изменяемый двунаправленный  | 
	
multiset<T>  | 
		multiset<T>::const_iterator  | 
		Константный двунаправленный  | 
	
map<Key,T>  | 
		map<Key,T>::iterator  | 
		Изменяемый двунаправленный  | 
	
map<Key,T>  | 
		map<Key,T>::const_iterator  | 
		Константный двунаправленный  | 
	
multimap<Key,T>  | 
		multimap<Key,T>::iterator  | 
		Изменяемый двунаправленный  | 
	
multimap<Key,T>  | 
		multimap<Key,T>::const_iterator  | 
		Константный двунаправленный  | 
	
