Ответ 1
Вы можете явно создавать и фиксировать ссылки на ссылки:
int x = 42;
const int& rx = x;
auto l = [&rx]() {
x = 5; // error: 'x' is not captured
rx = 5; // error: assignment of read-only reference 'rx'
};
Я создаю лямбда-функцию, которая требует доступа к множеству переменных в контексте.
const double defaultAmount = [&]{
/*ToDo*/
}();
Я бы предпочел не использовать [=]
в списке, так как мне не нужно делать много копий значений.
Меня беспокоит стабильность программы, если я использую [&]
, так как я не хочу, чтобы лямбда модифицировала набор захвата.
Могу ли я передать ссылку const? [const &]
не работает.
Возможно, хороший компилятор оптимизирует копии значений, поэтому [=]
является предпочтительным.
Вы можете явно создавать и фиксировать ссылки на ссылки:
int x = 42;
const int& rx = x;
auto l = [&rx]() {
x = 5; // error: 'x' is not captured
rx = 5; // error: assignment of read-only reference 'rx'
};
Список захвата ограничен тем, что можно захватить; в основном по значению или по ссылке (с именем или по умолчанию), указателем this
и ничего.
Из cppreference;
capture-list - список с нулевым или большим количеством разделенных запятыми, необязательно начинающийся с по умолчанию-захвата. Список захвата можно передать следующим образом (см. Ниже подробное описание):
[a,&b]
, гдеa
фиксируется по значению, аb
- по ссылке.[this]
отображает указательthis
по значению[&]
захватывает все автоматические переменные odr, используемые в теле лямбда по ссылке[=]
фиксирует все автоматические переменные odr, используемые в теле лямбда по значению[]
не фиксирует ничего
Вы можете создать локальный const&
для всего объекта, который вы хотите захватить, и использовать его в лямбда.
#include <iostream>
using namespace std;
int main()
{
int a = 5;
const int& refa = a;
const int b = [&]() -> int {
//refa = 10; // attempts to modify this fail
return refa;
}();
cout << a << " " << b << endl;
}
Захват может быть либо для всех ссылок, либо для явного списка, что требуется;
const int b = [&refa]()
Другой альтернативой является вовсе не локализовать локальные переменные. Затем вы создаете лямбду, которая принимает в качестве аргументов нужные вам переменные. Это может быть большим усилием по мере увеличения количества локальных переменных, но у вас больше контроля над тем, как лямбда принимает свои аргументы и может использовать данные.
auto lambda = [](const int& refa /*, ...*/) { */...*/ }
lambda(...);
К сожалению, грамматика С++ 11 не позволяет этого, поэтому нет.
Вы можете фиксировать постоянную ссылку на объект, а не на объект:
A a;
const A& ref_a = a;
const double defaultAmount = [&]{
ref_a.smth();
}();