Main Content

AUTOSAR C++14 Rule A5-1-2

Variables shall not be implicitly captured in a lambda expression

Description

Rule Definition

Variables shall not be implicitly captured in a lambda expression.

Rationale

In a lambda expression, you have the option to capture variables implicitly. For instance, this lambda expression

[&](std::int32_t var) {
   sum+ = var;
}
indicates that all local variables in the calling context are captured by reference. However, it is not immediately clear from this lambda expression:

  • If a variable in the body of the expression comes from the calling context.

    For instance, in the preceding lambda expression, it is not clear if sum is captured from the calling context or is a global variable.

  • If all variables captured from the calling context are used and whether the variables are modified or just read (If the variables are read, a by-copy capture is preferred).

If you capture variables explicitly in a lambda expression, you have more control on whether to capture by reference or copy. In addition, you or a reviewer can read the lambda expression and determine whether a variable was captured from the calling context.

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#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;
}

The lambda expression in the addEvenNumbers function captures all local variables in the calling context implicitly by reference and violates this rule. Some of the issues are:

  • Unless you go through the body of the expression, it is not clear which variables are used.

  • Though the variable divisor is only read and not modified, it is captured by reference. A by-copy capture is preferred.

The lambda expression in the addOddNumbers function captures each variable explicitly and does not violate this rule. Without looking at the body of the lambda expression, you can determine which variables are intended to be modified in the expression.

Check Information

Group: Expressions
Category: Required, Automated

Version History

Introduced in R2019b