Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Что значит for(int x : vector)

#cpp #vector #for


Недавно изучаю c++ по книге Страуструпа , и дошел до векторов, здесь в пример приведён
код для прохода по всем элементам вектора 

vector v = { 5,7,9,4,6,8 };
for (int x : v)
    cout << x << endl;


но мне не понятно что делает вот это условие:for(int x : v)
    


Ответы

Ответ 1



Range-based for-loop появился в языке начиная с С++11. По определению, в данном конкретном случае (для v типа std::vector) запись for (int x : v) cout << x << endl; эквивалентна vector::iterator b = v.begin(); vector::iterator e = v.end(); for (; b != e; ++b) { int x = *b; cout << x << endl; } В общем случае цикл вида for ( decl-x : v ) // тело цикла (где decl-x - это объявление), интерпретируется как { auto b = /* начало v */; auto e = /* конец v */; for (; b != e; ++b) { decl-x = *b; // тело исходного цикла } } А "начало v" и "конец v" определяются в зависимости от типа v: Если v - это массив размера n, то "начало" и "конец" - это просто v и v + n. Для объекта класс-типа v с членами begin и end (оба должны присутствовать) "начало" и "конец" - это результаты вызовов v.begin() и v.end(). Для всего остального "начало" и "конец" - это результаты вызовов begin(v) и end(v), где имена begin и end ищутся только в ассоциированных с v пространствах имен Некоторыми следствиями такой спецификации являются: Конец итерируемого диапазона запоминается до начала цикла, т.е. попытки расширения/сужения/переаллокации диапазона в процессе работы цикла не повлияют на запомненное значение и, в общем случае, ни к чему хорошему не приведут. Невозможно преопределить поведение для встроенных массивов путем перегрузки функций begin и end - эти функции будут просто проигнорированы. По аналогичной причине невозможно "снаружи" преопределить поведение для классов, у которых уже есть свои внутренние begin и end. Для типов, с которыми используются внешние begin и end, эти begin и end должны быть объявлены непосредственно в ассоциированных пространствах имен. Объявленные в охватывающих пространствах имен begin и end найдены не будут namespace N { struct S {}; } int *begin(N::S &s) { return 0; } int *end(N::S &s) { return 0; } int main() { N::S s; for (int x : s) // Ошибка - нет `begin` и `end` {} }

Ответ 2



Цикл for по диапазону. Такой "синтаксический сахар" for(int x : v) Переменная x поочередно принимает все значения из вектора (и не только вектора - это может быть другой стандартный контейнер или массив).

Комментариев нет:

Отправить комментарий