Недавно изучаю c++ по книге Страуструпа , и дошел до векторов, здесь в пример приведён код для прохода по всем элементам вектора
vector
но мне не понятно что делает вот это условие:for(int x : v)
Ответ
Range-based for-loop появился в языке начиная с С++11.
По определению, в данном конкретном случае (для v типа std::vector
for (int x : v)
// тело цикла
эквивалентна
auto b = v.begin();
auto e = v.end();
for (; b != e; ++b)
{
int x = *b;
// тело цикла
}
В общем случае цикл вида
for ( decl-x : v )
// тело цикла
(где decl-x - это объявление), интерпретируется как
{
auto b = /* начало v */;
auto e = /* конец v */;
for (; b != e; ++b)
{
decl-x = *b;
// тело цикла
}
}
А "начало v" и "конец v" определяются в зависимости от типа v
Для массива v это просто v и v + size
Для объекта класс-типа 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`
{}
}
Комментариев нет:
Отправить комментарий