exponenta event banner

AUTOSAR C++14 Rule A5-1-2

Переменные не должны быть неявно захвачены в лямбда выражении

Описание

Определение правила

Переменные не должны неявно захватываться в лямбда выражении.

Объяснение

В лямбда-выражении у вас есть опция неявно захватывать переменные. Например, это лямбда-выражение

[&](std::int32_t var) {
   sum+ = var;
}
указывает, что все локальные переменные в контексте вызова захватываются ссылкой. Однако из этого лямбда-выражения не сразу ясно:

  • Если переменная в теле выражения происходит из вызывающего контекста.

    Например, в предыдущем лямбда-выражении не ясно, sum получен из контекста вызова или является глобальной переменной.

  • Если используются все переменные, захваченные из вызывающего контекста, и изменяются или только считываются (Если считываются переменные, предпочтительным является захват путем копирования).

Если вы захватываете переменные явно в лямбда выражении, у вас есть больше контроля над тем, захватывать ли по ссылке или копие.В сложение вы или рецензент можете прочитать лямбда выражение и определить, была ли переменная получена из контекста вызова.

Поиск и устранение проблем

Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».

Примеры

расширить все

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdint>

void addEvenNumbers(std::vector<std::int32_t> numbers)
{
    std::int64_t sum = 0;
    std::int32_t divisor = 2;
    for_each(numbers.begin(), numbers.end(), [&] (std::int32_t y) //Noncompliant
    {
        if (y % divisor == 0)
        {
            std::cout << y << std::endl; 
            sum += y;
        }
    });
 
    std::cout << sum << std::endl;
}

void addOddNumbers(std::vector<std::int32_t> numbers)
{
    std::int64_t sum = 0;
    std::int32_t divisor = 2;
    for_each(numbers.begin(), numbers.end(), [&sum, divisor] (std::int32_t y) //Compliant
    {
        if (y % divisor != 0)
        {
            std::cout << y << std::endl; 
            sum += y;
        }
    });
 
    std::cout << sum << std::endl;
}

Лямбда-выражение в addEvenNumbers функция неявно захватывает все локальные переменные в контексте вызова при помощи ссылки и нарушает это правило. К числу некоторых вопросов относятся следующие:

  • Если вы не проходите через тело выражения, не ясно, какие переменные используются.

  • Хотя переменная divisor считывается и не изменяется, захватывается ссылкой. Предпочтительным является захват по копиям.

Лямбда-выражение в addOddNumbers функция явно захватывает каждую переменную и не нарушает это правило. Не рассматривая тело лямбда-выражения, можно определить, какие переменные предназначены для изменения в выражении.

Проверяйте информацию

Группа: Выражения
Категория: Необходимый, Автоматизированный
Введенный в R2019b