cout << *q << ' '; //
cout << endl;
}
Спецификатор auto
позволяет библиотеке самостоятельно определить конечный указатель и избавить от необходимости писать тип, значение которого возвращает функция begin()
. Во внешнем цикле этот тип — указатель на массив из четырех целых чисел. Во внутреннем цикле этот тип — указатель на тип int
.
Псевдоним типа (см. раздел 2.5.1) может еще больше облегчить чтение, написание и понимание указателей на многомерные массивы. Рассмотрим пример.
using int_array = int[4]; //
//
typedef int int_array[4]; //
//
//
//
for (int_array *p = ia; p != ia + 3; ++p) {
for (int *q = *p; q != *p + 4; ++q)
cout << *q << ' ';
cout << endl;
}
Код начинается с определения int_array
как имени для типа "массив из четырех целых чисел". Это имя типа используется для определения управляющей переменной внешнего цикла for
.
Упражнение 3.43. Напишите три разных версии программы для вывода элементов массива ia
. Одна версия должна использовать для управления перебором серийный оператор for
, а другие две — обычный цикл for
, но в одном случае использовать индексирование, а в другом — указатели. Во всех трех программах пишите все типы явно, т.е. не используйте псевдонимы типов и спецификаторы auto
или decltype
для упрощения кода.
Упражнение 3.44. Перепишите программы из предыдущего упражнения, используя псевдоним для типа управляющих переменных цикла.
Упражнение 3.45. Перепишите программы снова, на сей раз используя спецификатор auto
.
Резюме
Одними из важнейших библиотечных типов являются vector
и string
. Строка — это последовательность символов переменной длины, а вектор — контейнер объектов единого типа.
Итераторы обеспечивают косвенный доступ к хранящимся в контейнере объектам. Итераторы используются для доступа и перемещения между элементами в строках и векторах.
Массивы и указатели на элементы массива обеспечивают низкоуровневые аналоги библиотечных типов vector
и string
. Как правило, предпочтительней использовать библиотечные классы, а не их низкоуровневые альтернативы, массивы и указатели, встроенные в язык.
Термины
Арифметические действия с итераторами (iterator arithmetic). Операции с итераторами векторов и строк. Добавление и вычитание целого числа из итератора приводит к изменению позиции итератора на соответствующее количество элементов вперед или назад от исходного. Вычитание двух итераторов позволяет вычислить дистанцию между ними. Арифметические действия допустимы лишь для итераторов, относящихся к элементам того же контейнера.
Арифметические действия с указателями (pointer arithmetic). Арифметические операции, допустимые для указателей. Указатели на массивы поддерживают те же операции, что и арифметические действия с итераторами.
Индекс (index). Значение, используемое в операторе индексирования для указания элемента, возвращаемого из строки, вектора или массива.
Инициализация значения (value initialization). Инициализация, в ходе которой объекты встроенного типа инициализируются нулем, а объекты класса — при помощи стандартного конструктора класса. Объекты типа класса могут быть инициализированы значением, только если у класса есть стандартный конструктор. Используется при инициализации элементов контейнера, когда указан его размер, но не указан инициализирующий элемент. Элементы инициализируются копией значения, созданного компилятором.
Инициализация копией (copy initialization). Форма инициализации, использующая знак =
. Вновь созданный объект является копией предоставленного инициализатора.
Итератор после конца (off-the-end iterator). Итератор, возвращаемый функцией end()
. Он указывает не на последний существующий элемент контейнера, а на позицию за его концом, т.е. на несуществующий элемент.
Контейнер (container). Тип, объекты которого способны содержать коллекцию объектов определенного типа. К контейнерным относится тип vector
.