[]Пустой список захвата. Лямбда-выражение не может использовать переменные из содержащей функции. Лямбда-выражение может использовать локальные переменные, только если оно захватывает их
[names]names — разделяемый запятыми список имен, локальных для содержащей функции. По умолчанию переменные в списке захвата копируются. Имя, которому предшествует знак &, захватывается по ссылке
[&]Неявный захват по ссылке. Сущности из содержащей функции используются в теле лямбда-выражения по ссылке
[=]Неявный захват по значению. Сущности из содержащей функции используются в теле лямбда-выражения как копии
[&, identifier_list]identifier_list — разделяемый запятыми список любого количества переменных из содержащей функции. Эти переменные захватываются по значению; любые неявно захваченные переменные захватывается по ссылке. Именам в списке identifier_list не могут предшествовать символы &
[=, reference_list]Переменные, включенные в список reference_list, захватываются по ссылке; любые неявно захваченные переменные захватывается по значению. Имена в списке reference_list не могут включать часть this и должны предваряться символом &
Захват по ссылке

Можно также определять лямбда-выражения, захватывающие переменные по ссылке. Например:

void fcn2() {

 size_t v1 = 42; // локальная переменная

 // объект f2 содержит ссылку на v1

 auto f2 = [&v1] { return v1; };

 v1 = 0;

 auto j = f2(); // j = 0; f2 ссылается на v1; он не хранится в j

}

Символ & перед v1 указывает, что переменная v1 должна быть захвачена как ссылка. Захваченная по ссылке переменная действует так же, как любая другая ссылка. При использовании переменной в теле лямбда-выражения фактически применяется объект, с которым связана эта ссылка. В данном случае, когда лямбда-выражение возвращает v1, возвращается значение объекта, на который ссылается переменная v1.

Захват ссылок имеет те же проблемы и ограничения, что и возвращение ссылок (см. раздел 6.1.1). При захвате переменной по ссылке следует быть уверенным, что объект, на который она ссылается, существует на момент выполнения лямбда-выражения. Переменные, захваченные лямбда-выражением, являются локальными, они перестают существовать сразу, как только функция завершится. Если лямбда-выражение продолжит выполняться после завершения функции, то используемые ею локальные переменные окажутся несуществующими.

Иногда захват по ссылке необходим. Например, может понадобиться, чтобы функция biggies() получала ссылку на поток ostream для записи символа, используемого как разделитель:

void biggies(vector &words,

             vector::size_type sz,

             ostream &os = cout, char c = ' ') {

 // код, переупорядочивающий слова как прежде

 // оператор вывода количества, пересмотренный для вывода os

 for_each(words.begin(), words.end(),

          [&os, c](const string &s) { os << s << c; });

}

Объекты потока ostream нельзя копировать (см. раздел 8.1.1); единственный способ захвата объекта os — это ссылка (или указатель).

При передаче лямбда-выражения функции, как и в случае вызова функции for_each(), лямбда-выражение выполняется немедленно. Захват объекта os по ссылке хорош потому, что переменные в функции biggies() существуют во время выполнения функции for_each().

Перейти на страницу:

Похожие книги