9.2.3. Функции-члены begin() и end()

Функции-члены begin() и end() (см. раздел 3.4.1) возвращают итераторы на первый и следующий после последнего элементы контейнера соответственно. Эти итераторы, как правило, используют при создании диапазона итераторов, охватывающего все элементы контейнера.

Как показано в табл. 9.2, есть несколько версий этих функций: имена которых начинаются с буквы r возвращают реверсивные итераторы (рассматриваются в разделе 10.4.3), а с буквы c — возвращают константную версию соответствующего итератора:

list<string> a = {"Milton", "Shakespeare", "Austen"};

auto it1 = a.begin();  // list<string>::iterator

auto it2 = a.rbegin(); // list<string>::reverse_iterator

auto it3 = a.cbegin(); // list<string>::const_iterator

auto it4 = a.crbegin();// list<string>::const_reverse_iterator

Функции, имена которых не начинаются с буквы c, перегружены. Таким образом, фактически есть две функции-члена begin(). Одна является константной (см. раздел 7.1.2) и возвращает тип const_iterator контейнера. Вторая не константна и возвращает тип iterator контейнера. Аналогично для функций rbegin(), end() и rend(). При вызове такой функции-члена для неконстантного объекта используется версия, возвращающая тип iterator. Константная версия итераторов будет получена только при вызове этих функций для константного объекта. Подобно указателям и ссылкам на константу, итератор типа iterator можно преобразовать в соответствующий итератор типа const_iterator, но не наоборот.

Версии этих функций, имена которых не начинаются с буквы с, были введены согласно новому стандарту для обеспечения использования ключевого слова auto с функциями begin() и end() (см. раздел 2.5.2). Прежде не было никакого иного выхода, кроме как явно указать необходимый тип итератора:

// тип указан явно

list<string>::iterator it5 = a.begin();

list<string>::const_iterator it6 = a.begin();

// iterator или const_iterator в зависимости от типа а

auto it7 = a.begin();  // const_iterator только если a константа

auto it8 = a.cbegin(); // it8 - const_iterator

Когда с функциями begin() или end() используется ключевое слово auto, тип возвращаемого итератора зависит от типа контейнера. То, как предполагается использовать итератор, несущественно. Версии c позволяют получать итератор типа const_iterator независимо от типа контейнера.

Когда доступ на запись не нужен, используйте версии cbegin() и cend().

Упражнения раздела 9.2.3

Упражнение 9.9. В чем разница между функциями begin() и cbegin()?

Упражнение 9.10. Каковы типы следующих четырех объектов?

vector<int> v1;

const vector<int> v2;

auto it1 = v1.begin(), it2 = v2.begin();

auto it3 = v1.cbegin(), it4 = v2.cbegin();