メインコンテンツ

AUTOSAR C++14 Rule A5-1-2

Variables shall not be implicitly captured in a lambda expression

説明

ルール定義

ラムダ式において変数を暗黙的に取得してはなりません。

根拠

ラムダ式には変数を暗黙的に取得するオプションがあります。例として、次のラムダ式を考えます。

[&](std::int32_t var) {
   sum+ = var;
}
このラムダ式は、呼び出しコンテキスト内のすべてのローカル変数が参照によって取得されることを示しています。しかし、このラムダ式では、次の事柄がすぐにはわかりません。

  • 式本体に含まれる変数が呼び出しコンテキストに由来するものかどうか。

    たとえば、前述のラムダ式では、sum が呼び出しコンテキストから取得されたものか、グローバル変数なのかが明らかではありません。

  • 呼び出しコンテキストから取得されたすべての変数が使用されているかどうか。また、それらの変数が変更されているのか、読み取られただけなのか (変数が読み取られたものである場合、コピーによる取得が好ましい)。

ラムダ式で変数を明示的に取得すれば、参照またはコピーのいずれによって取得するかをより明確に制御できます。加えて、開発者やレビュー担当者がラムダ式を見て、変数が呼び出しコンテキストから取得されたものであるかどうかを判断できるようになります。

トラブルシューティング

ルール違反が想定されるものの、Polyspace® から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#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 のラムダ式は、各変数を明示的に取得しており、このルールに違反していません。ラムダ式の本体を確認しなくても、式内のどの変数が変更されることになっているかを判断できます。

チェック情報

グループ:
カテゴリ: Required、Automated

バージョン履歴

R2019b で導入