Захват членами класса ценности
Есть ли способ, когда записывать лямбда-функцию внутри функции-члена, для захвата полей охватывающего класса по значению? По умолчанию catch-all =
не работает, потому что когда я ссылаюсь на переменную внутри лямбда, я получаю вместо нее разыменование из захваченного этого указателя, а также явно именование переменной в списке захвата, потому что я получаю две ошибки компиляции: capture of non-variable <name>
и ‘this’ was not captured for this lambda function
Ответы
Ответ 1
Нет, данные не могут быть записаны по значению. Лямбда может захватывать только два вида вещей:
- указатель
this
и
- нестатические локальные переменные (т.е. переменные с продолжительностью автоматического хранения).
Как было отмечено в комментариях ildjarn, вы можете создать локальную переменную с копией значения элемента данных и захватить эту локальную переменную по значению.
Я бы сказал, что если бы разрешался явный захват по значению элемента данных, это могло бы ввести в заблуждение, поскольку поведение явного захвата будет отличаться от поведения неявного захвата. Например, учитывая доступный элемент данных типа int
с именем m
, было бы странно, что следующее приведет к различным результатам:
[=] () mutable { m = 1; } // we modify this->m
[=m]() mutable { m = 1; } // we modify the copy of m that was captured
Ответ 2
Да, просто напишите конструкцию [<new name>=<your class field>]
.
Например:
class MyClass {
int a;
void foo() {
auto my_lambda = [a_by_val=a] {
// do something with a_by_val
}
my_lambda();
}
}
Ответ 3
С++ - это язык скорости, и одной из самых важных особенностей дизайна языка является производительность. Если стандартные дизайнеры хотят реализовать идиому как способ захватить все переменные класса по стоимости, подумайте о действительно огромном классе и скажите мне, хотите ли вы захватить их все по стоимости? даже для захвата всех переменных, объявленных в функции (включая this
), существует 2 способа:
-
по значению: переменные, определенные в функции, оставляют в стеке, поэтому они не могут быть мульти мегабайтами, но классы, использующие кучу типа vector
, все еще могут быть огромными. Поэтому позаботьтесь об этом!
-
по ссылке: это фактически сохраняет указатель стека.
Итак, вы видите, что нет эффективного способа захвата всех переменных класса со значением, но вы можете сделать локальную копию этого класса в своей функции, а затем захватить его по ссылке!