У меня есть этот код:
int i = 0;
[&i](){i++;}();
Но я могу опустить я и просто использовать:
[&](){i++;}();
Какова цель указания &i
? (и аналогично =var
и =
). Это влияет на время компиляции или производительность выполнения?
У меня есть этот код:
int i = 0;
[&i](){i++;}();
Но я могу опустить я и просто использовать:
[&](){i++;}();
Какова цель указания &i
? (и аналогично =var
и =
). Это влияет на время компиляции или производительность выполнения?
&i
означает, что только i
записывается как ссылка, а &
означает, что все переменные, которые используются в лямбда, захватываются из области.
int i = 0, j = 10;
[&i]{ i++; j++;}(); //error: j is not captured by reference
[&]{ i++; j++;}(); //ok: both variables are captured by reference
Подход &i
обеспечивается языком, чтобы ограничить количество захваченных переменных. С++ предоставляет вам полный контроль над захваченными переменными, относительно того, какие конкретные переменные захватывать, как захватывать (по значению или ссылке).
Те же рассуждения с i
и =
:
int i = 0, j = 10;
[i]{ i++; j++;}(); //error: j is not captured (only i is captured by value)
[=]{ i++; j++;}(); //ok: both variables are captured by value
//more
[&i, j]{ i++; j++;}(); //ok: captured i by reference, j by value
Надеюсь, что это поможет.
Иногда вам может понадобиться захватывать разные переменные по-разному:
std::vector<int> v { 7, 8, 9, 10, 11 };
int n = 3;
//Capture v by reference and n by value:
auto getNth = [&v, n](){ return v[n]; };
//Behavior:
n = 9999;
getNth(); //returns 10 - changing n didn't affect the lambda
v[3] = 42;
getNth(); //returns 42 - changing v did affect the lambda
Вот почему доступен более подробный синтаксис.
Эта функция не касается производительности, связанной с читабельностью и ремонтопригодностью. Когда вы используете синтаксис скрытого захвата [&]
или [=]
, тогда он скрывает состояние, которое разделяется между исходным методом и телом лямбды. Это может повлиять на проблемы обслуживания в методе, если разработчик неправильно принимает значение, и оно не фиксируется. Имея предложение захвата, он делает гораздо более явным то, на чем рассчитывается лямбда.
Какова цель задания & i? (и аналогично = var и =). Это влияет на время компиляции или производительность выполнения?
Вы можете указать, будут ли значения захватываться по ссылке или по значению. Использование [&]
указывает, что вы хотите захватить все по ссылке, но вы также можете написать lambda, который делает:
[=, &i, &j]()
Что говорит о захвате всего по значению, за исключением захвата i
и j
по ссылке.
В вашем конкретном случае это не полезно - вы можете просто сказать, что захватить все по ссылке, а компилятор определит, что вы используете i
и фиксируете его по ссылке - но когда вы имеете дело с несколькими переменными будучи захваченным, С++ позволяет вам контролировать, как каждый из них будет снят индивидуально.
Если вы перечислите переменные для захвата, вы четко указываете, что хотите. И вы получаете ошибку компилятора, если используете то, что не хотели (вы его не захватили). Это может быть хорошо (вы допустили ошибку в реализации) или что-то плохое (вы просто забыли перечислить переменную).
Это действительно зависит от конкретного сценария. Я бы добавил, что чем сложнее лямбда и/или чем сложнее содержащая область видимости, тем лучше будет четко описывать, что вы делаете.
Есть дополнительная точка, и это смешение захвата по значению и захват по ссылке - вы должны быть явным, по крайней мере, в одном из них. Пример:
int i, j, k;
auto f = [=, &i]() { /* code which can read i, j and k but can only modify i */ };