exponenta event banner

Правило AUTOSAR C++ 14 A5-1-4

Объект лямбда-выражения не должен переживать ни один из своих объектов, захваченных ссылкой

Описание

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

Объект лямбда-выражения не должен переживать ни один из своих объектов, захваченных ссылкой.

Объяснение

Правило помечает случаи, когда лямбда-выражение захватывает объект по ссылке и потенциально можно получить доступ к захваченному объекту вне его области действия. Такая ситуация возникает, если объект лямбда-выражения переживает объект, захваченный ссылкой.

Например, рассмотрим эту функцию createFunction:

std::function<std::int32_t()> createFunction() {
   std::int32_t localVar = 0;
   return ([&localVar]() -> std::int32_t {
       localVar = 1;
       return localVar;
   });
}

createFunction возвращает объект лямбда-выражения, который захватывает локальную переменную localVar по ссылке. Объем localVar ограничивается createFunction но возвращенный объект лямбда-выражения имеет гораздо большую область действия.

Эта ситуация может привести к попытке доступа к локальному объекту localVar за его пределами. Например, когда вы звоните createFunction и назначить возвращенный объект лямбда-выражения другому объекту aFunction:

auto aFunction = createFunction();
а затем вызовите новый объект aFunction:
std::int32_t someValue = aFunction();
захваченная переменная localVar больше не входит в область действия. Поэтому значение, возвращенное из aFunction не определен.

Если функция возвращает лямбда-выражение, чтобы избежать доступа к захваченному объекту вне его области действия, убедитесь, что лямбда-выражение захватывает все объекты копией. Например, можно переписать createFunction как:

std::function<std::int32_t()> createFunction() {
   std::int32_t localVar = 0;
   return ([localVar]() mutable -> std::int32_t {
       localVar = 1;
       return localVar;
   });
}

Поиск неисправностей

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

Примеры

развернуть все

auto createAdder(int amountToAdd) {
  int addThis = amountToAdd; //Noncompliant
  auto adder = [&] (int initialAmount) {
      return (initialAmount + addThis);
  };
  return adder;
}
 
void foo() {
  auto AddByTwo = createAdder(2);
  int res = AddByTwo(10);
}

auto createMultiplier(int amountToMultiply) {
  int multiplyThis = amountToMultiply; //Compliant
  auto adder = [=] (int initialAmount) {
      return (initialAmount + multiplyThis);
  };
  return adder;
}


void bar() {
  auto MultiplyByTwo = createMultiplier(2);
  int res = MultiplyByTwo(10);
}

В этом примере createAdder функция определяет лямбда-выражение adder который захватывает локальную переменную addThis по ссылке. Объем addThis ограничивается createAdder функция. Когда объект AddByTwo, который возвращается createAdder, называется, ссылка на переменную addThis доступен за пределами его области действия. При обращении таким образом значение addThis не определен.

Проблема не возникает с createMultiplier функция, которая возвращает лямбда-выражение, которое захватывает локальные переменные копированием.

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

Группа: Выражения
Категория: Обязательно, Автоматизировано
Представлен в R2019b