С++ для начинающих


Еще раз об итераторах


Следующая реализация шаблона функции не компилируется. Можете ли вы сказать, почему?

// в таком виде это не компилируется

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();



Содержание раздела