Мои параметры лямбды действительно затеняют моих местных жителей?

Я имею дело с кодом C, который берет некоторые данные и передает их функции, переданной в:

void foo(int* data, void (*fun)(int*)){
  (*fun)(data);
};

Следующие работы без предупреждения:

void bar(int* data){};

int main(){
  int data=0;
  foo(&data,bar);
}

Однако, если я использую лямбду вместо:

int main(){

  int data=0;
  foo(&data,[](auto data){});
}

Я получаю следующее предупреждение:

warning: declaration of ‘data’ shadows a previous local [-Wshadow]
   foo(&data,[](auto data){});
                         ^
o.cpp:14:7: note: shadowed declaration is here
   int data=0;

Но я думал, что пустая группа захвата исключит первое создание во время поиска.

Является ли это предупреждение законным?
Почему пустого захвата недостаточно, чтобы избежать предупреждений?

2 ответа

Имена из области охвата лямбды также входят в область действия лямбды.

Имена, которые не были захвачены, могут все еще использоваться, пока они не используются odr. Должны быть записаны только переменные, используемые odr. Пример:

#include <iostream>

template<typename T> void foo(const int *, T f) { std::cout << f(5) << '\n'; }

int main()
{
    const int data=0;
    foo(&data,[](int baz){
        return data;
    });
}

Поскольку чтение константного выражения не использует odr, этот код является правильным и data относится к переменной в main,

Эта программа выводит 0, но если вы измените int baz в int data, это выводит 5,

В отношении MISRA C++ 2008: идентификатор, объявленный во внутренней области видимости, никогда не должен иметь того же имени, что и идентификатор, объявленный во внешней области видимости.

В вашем примере int data объявляется во внешней области видимости, но переходит во внутреннюю область видимости лямбды через ссылку. Проблема в том, что у вас также есть параметр в списке параметров вашей лямбды, называемый данными (внутренняя область). Это приводит к сокрытию переменной данных от внешней области видимости в лямбде.

Кстати. Также ваш первый пример с указателем на функцию должен быть переписан, потому что также существует конфликт с именами идентификаторов во внутренней и внешней области видимости. В этом случае это не так уж и плохо, потому что во внутренней оценке используется только одна переменная данных. Однако, когда переменные списка параметров и переменные из внешней области видимости, вызывающей функцию, имеют одно и то же имя, это может привести к путанице у программистов, и этого также следует избегать.

Другие вопросы по тегам