exponenta event banner

Правило AUTOSAR C++ 14 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