Захват членами класса ценности

Есть ли способ, когда записывать лямбда-функцию внутри функции-члена, для захвата полей охватывающего класса по значению? По умолчанию 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, все еще могут быть огромными. Поэтому позаботьтесь об этом!

  • по ссылке: это фактически сохраняет указатель стека.

Итак, вы видите, что нет эффективного способа захвата всех переменных класса со значением, но вы можете сделать локальную копию этого класса в своей функции, а затем захватить его по ссылке!