- •Ооп: Лекция 7. Стандартная библиотека шаблонов ч.1
- •Адаптеры stl-контейнеров
- •Категории итераторов
- •Итераторы stl-контейнеров
- •Реверс-итератор можно преобразовать в обычный итератор через метод base().
- •Примеры алгоритмов и итераторов
- •Недействительные итераторы
- •При удалении все элементы, стоящие правее, сдвигаются на одну ячейку влево. При этом, итератор, по-прежнему указывает на ту же самую позицию:
- •Затем, итератор инкрементируется, указывая уже на следующую позицию:
- •При работе с другими контейнерами также следует соблюдать осторожность, и задумываться о ситуациях, при которых могут появляться недействительные итераторы:
- •Алгоритмы стандартной библиотеки
- •Пример использования изученных элементов stl
- •Полные примеры из лекции
Итераторы stl-контейнеров
Получить итератор любого STL-контейнера, указывающий на начало последовательности, можно используя метод begin(), а на элемент, следующий за последним - используя метод end(). Конкретный тип каждого итератора зависит от реализации стандартной библиотеки, но доступен по стандартному синониму типа iterator:
std::vector< int > v( 10 );
std::vector< int >::iterator it = v.begin();
Контейнеры также предоставляют константные итераторы - это уточнение итератора любой категории, запрещающее модификацию последовательности. Такие итераторы также получить методами begin/end (компилятор определяет какой именно вариант нужен из контекста), а стандартный синоним называется const_iterator:
std::vector< int > v( 10 );
std::vector< int >::const_iterator it = v.begin();
При помощи константных итераторов можно перебирать контейнер теми же способами, что и обычный итератор, но к данным разрешается только обращение с целью чтения. Любая попытка записи данного через константный итератор не пройдет компиляцию.
Записывать вложенные имена типов итераторов не слишком приятно, потому рекомендуется использовать ключевое слово auto для автоматического вывода типа:
std::vector< int > v( 10 );
auto it = v.begin(); // возможно обычный, возможно и константный итератор
Методы begin() и end() перегружены в вариантах с модификатором const и без него, соответственно возвращают константные или обычные итераторы. В приведенном выше примере, использующем ключевое слово auto, может быть не очевидным тип результирующего итератора - константный или обычный. В ряде случаев, могут оказаться необходимыми именно константные итераторы. В контейнерах существует пара похожих методов - cbegin() и cend(), которые всегда и при любых условиях возвращают именно константные итераторы:
std::vector< int > v( 10 );
auto it = v.сbegin(); // однозначно здесь константный итератор
Также, контейнеры предоставляют реверс-итераторы, которые инвертируют направление итерирования. Когда на таком итераторе вызывается операция ++, она транслируется в фактическую --, и наоборот. Получить такие итераторы можно вызвав методы rbegin/rend:
std::vector< int > v( 10 );
std::vector< int >::reverse_iterator rit1 = v.rbegin();
std::vector< int >::const_reverse_iterator rit2 = v.rbegin();
Если обычные итераторы begin/end можно графически представить таким образом:
то реверс-итератор начинается с последнего элемента и заканчивается элементом, условно предшествующим первому:
Например, используя реверс-итератор и созданный нами ранее алгоритм поиска значений, можно искать элементы начиная с конца, а не с начала:
int main ()
{
std::vector< int > v;
for ( int i = 0; i < 10; i++ )
v.push_back( i );
auto it = MyFind( v.rbegin(), v.rend(), 0 );
assert( ( it.base() - v.begin() ) == 1 ) );
}
Реверс-итератор можно преобразовать в обычный итератор через метод base().
Для обеспечения целостной картины в контейнерах также существует пара методов crbegin() и crend(), которые независимо от контекста возвращают константные реверс-итераторы.
Очевиден следующий вывод - чем больше требований у алгоритма к итератору, тем меньшее число структур данных может предоставить такой итератор. Это ограничивает использование в алгоритмах. Аналогично, чем меньше требований у алгоритма к итератору, тем большее число структур данных может быть использовано вместе с этим алгоритмом.
