Лямбда-выражения c++: разница между "изменчивый" и захват по ссылке
В C++ вы можете объявить лямбды, например, так:
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << 'n'; };
auto b = [&]() { ++x; std::cout << x << 'n'; };
оба позвольте мне изменить x
, Так в чем же разница?
1 ответ:
что происходит
первый будет изменять только свою собственную копию
x
и оставьте снаружиx
без изменений. Второй будет изменять за пределамиx
.добавить инструкцию печати после каждой попытки:
a(); std::cout << x << "----\n"; b(); std::cout << x << '\n';
ожидается, что это для печати:
6 5 ---- 6 6
почему
это может помочь рассмотреть, что лямбда
[...] expressions provide a concise way to create simple function objects
(см. [expr.подтянутый.лямда стандарта).у них есть [...] оператор вызова общедоступной встроенной функции [...] который объявлен как
const
функция-член, но только [...] если и только если лямбда-выражениеparameter-declaration-clause
не следуетmutable
(курсивный текст-цитаты из стандарта).вы можете думать как бы
int x = 5; auto a = [=]() mutable { ++x; std::cout << x << '\n'; }; ==> int x = 5; class __lambda_a { int x; public: __lambda_a () : x($lookup-one-outer$::x) {} inline void operator() { ++x; std::cout << x << '\n'; } } a;
и
auto b = [&]() { ++x; std::cout << x << '\n'; }; ==> int x = 5; class __lambda_b { int &x; public: __lambda_b() : x($lookup-one-outer$::x) {} inline void operator() const { ++x; std::cout << x << '\n'; } // ^^^^^ } b;
Q: но если это
const
функция, почему я все еще могу изменитьx
?A: ты только меняешься снаружи
x
. Собственная лямбдаx
- это ссылка, а операция++x
не изменяет ссылка, а ссылка на значение.это работает, потому что в C++ константа указателя/ссылки не изменяет константу указателя/ссылки, видимого через него.