Ответ
Ключевое слово mutable у лямбды снимает константность с захваченных по значению переменных, позволяя изменять их копии внутри тела лямбды. Без mutable такие захваченные копии являются const.
Простой пример — счётчик вызовов:
auto make_counter() {
int call_count = 0; // Локальная переменная
// Захватываем call_count по значению, но mutable позволяет его менять
return [call_count]() mutable {
++call_count;
return call_count;
};
}
auto counter = make_counter();
std::cout << counter(); // 1
std::cout << counter(); // 2
std::cout << counter(); // 3
// Важно: внешняя call_count (уже уничтоженная) никогда не менялась.
Что происходит на практике:
- При создании лямбды
[call_count]значение переменнойcall_countкопируется в неявный член анонимного класса лямбды. - Без
mutableоператор вызова (operator()) этого класса являетсяconst-методом, поэтому менять члены класса нельзя. - С
mutableоператор вызова становится не-const, и изменять захваченные копии разрешается.
Важные ограничения:
mutableвлияет только на захват по значению. Для захвата по ссылке ([&x]) он не нужен, так как лямбда и так может менять исходный объект.- Это не делает лямбду потокобезопасной. Если лямбда с состоянием вызывается из нескольких потоков, требуется синхронизация.
- Использование
mutableдля изменения захваченных по значению объектов может быть признаком неоптимального дизайна — иногда лучше явно захватить по ссылке или использоватьstd::reference_wrapper.