AUTOSAR C++14 Rule 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