Подтвердить что ты не робот

Какова цель указания захваченной переменной в лямбда-выражении?

У меня есть этот код:

int i = 0;
[&i](){i++;}();

Но я могу опустить я и просто использовать:

[&](){i++;}();

Какова цель указания &i? (и аналогично =var и =). Это влияет на время компиляции или производительность выполнения?

4b9b3361

Ответ 1

&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

Надеюсь, что это поможет.

Ответ 2

Иногда вам может понадобиться захватывать разные переменные по-разному:

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

Вот почему доступен более подробный синтаксис.

Ответ 3

Эта функция не касается производительности, связанной с читабельностью и ремонтопригодностью. Когда вы используете синтаксис скрытого захвата [&] или [=], тогда он скрывает состояние, которое разделяется между исходным методом и телом лямбды. Это может повлиять на проблемы обслуживания в методе, если разработчик неправильно принимает значение, и оно не фиксируется. Имея предложение захвата, он делает гораздо более явным то, на чем рассчитывается лямбда.

Ответ 4

Какова цель задания & i? (и аналогично = var и =). Это влияет на время компиляции или производительность выполнения?

Вы можете указать, будут ли значения захватываться по ссылке или по значению. Использование [&] указывает, что вы хотите захватить все по ссылке, но вы также можете написать lambda, который делает:

[=, &i, &j]()

Что говорит о захвате всего по значению, за исключением захвата i и j по ссылке.

В вашем конкретном случае это не полезно - вы можете просто сказать, что захватить все по ссылке, а компилятор определит, что вы используете i и фиксируете его по ссылке - но когда вы имеете дело с несколькими переменными будучи захваченным, С++ позволяет вам контролировать, как каждый из них будет снят индивидуально.

Ответ 5

Если вы перечислите переменные для захвата, вы четко указываете, что хотите. И вы получаете ошибку компилятора, если используете то, что не хотели (вы его не захватили). Это может быть хорошо (вы допустили ошибку в реализации) или что-то плохое (вы просто забыли перечислить переменную).

Это действительно зависит от конкретного сценария. Я бы добавил, что чем сложнее лямбда и/или чем сложнее содержащая область видимости, тем лучше будет четко описывать, что вы делаете.

Есть дополнительная точка, и это смешение захвата по значению и захват по ссылке - вы должны быть явным, по крайней мере, в одном из них. Пример:

int i, j, k;

auto f = [=, &i]() { /* code which can read i, j and k but can only modify i */ };