Functions
F.53
Избегайте захвата по ссылке в лямбдах, которые используются нелокально, включая возвращаемые, хранящиеся в куче или передаваемые другому потоку
Причина
Указатели и ссылки на локальные переменные не должны пережить свою область видимости. Лямбды, захватывающие по ссылке, — это ещё одно место хранения ссылки на локальный объект, и не следует делать это, если они (или их копия) переживают область видимости.
Пример (плохой)
int local = 42;
// Хотим ссылку на local.
// Заметьте, что после выхода программы из этой области видимости
// local больше не существует, поэтому
// вызов process() будет иметь неопределённое поведение!
thread_pool.queue_work([&] { process(local); });
Пример (хороший)
int local = 42;
// Хотим копию local.
// Поскольку копия local сделана, она будет
// всегда доступна для вызова.
thread_pool.queue_work([=] { process(local); });
Примечание
Если нелокальный указатель должен быть захвачен, рассмотрите использование unique_ptr; это обрабатывает и время жизни, и синхронизацию.
Если указатель this должен быть захвачен, рассмотрите использование захвата [*this], который создаёт копию всего объекта.
Контроль
- (Простой) Предупреждать, когда список захвата содержит ссылку на локально объявленную переменную
- (Сложный) Помечать, когда список захвата содержит ссылку на локально объявленную переменную и лямбда передаётся в не-
constи нелокальный контекст