Лямбда-выражения 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++ константа указателя/ссылки не изменяет константу указателя/ссылки, видимого через него.