Еще раз об итераторах
Следующая реализация шаблона функции не компилируется. Можете ли вы сказать, почему?
// в таком виде это не компилируется
template < typename type >
int
count( const vector< type > &vec, type value )
{
int count = 0;
vector< type >::iterator iter = vec.begin();
while ( iter != vec.end() )
if ( *iter == value )
++count;
return count;
}
Проблема в том, что у ссылки vec есть спецификатор const, а мы пытаемся связать с ней итератор без такого спецификатора. Если бы это было разрешено, то ничто не помешало бы нам модифицировать с помощью этого итератора элементы вектора. Для предотвращения подобной ситуации язык требует, чтобы итератор, связанный с const-вектором, был константным. Мы можем сделать это следующим образом:
// правильно: это компилируется без ошибок
vector< type>::const_iterator iter = vec.begin();
Требование, чтобы с const-контейнером был связан только константный итератор, аналогично требованию о том, чтобы const-массив адресовался только константным указателем. В обоих случаях это вызвано необходимостью гарантировать, что содержимое const-контейнера не будет изменено.
Операции begin() и end() перегружены и возвращают константный или неконстантный итератор в зависимости от наличия спецификатора const в объявлении контейнера. Если дана такая пара объявлений:
vector< int > vec0;
const vector< int > vec1;
то при обращениях к begin() и end() для vec0 будет возвращен неконстантный, а для vec1 – константный итератор:
vector< int >::iterator iter0 = vec0.begin();
vector< int >::const_iterator iter1 = vec1.begin();
Разумеется, присваивание константному итератору неконстантного разрешено всегда. Например:
// правильно: инициализация константного итератора неконстантным
vector< int >::const_iterator iter2 = vec0.begin();