我的lambda参数真的影响了我的当地人吗?

时间:2016-05-24 03:39:59

标签: c++ gcc lambda clang compiler-warnings

我正在处理一些带有一些数据的C代码,并将它转发给传入的函数:

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

以下作品未经警告:

void bar(int* data){};

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

但是,如果我改用lambda:

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 个答案:

答案 0 :(得分:4)

lambda的封闭范围中的名称也在lambda的范围内。

可能仍会使用未捕获的名称,只要它们不是 odr-used 即可。只能捕获 odr-used 变量。例如:

#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-use ,所以此代码是正确的,data引用main中的变量。

此计划会输出0,但如果您将int baz更改为int data,则会输出5

答案 1 :(得分:0)

参考MISRA C ++ 2008: 在内部作用域中声明的标识符永远不应与在外部作用域中声明的标识符具有相同的名称。

在您的示例中,int data在外部作用域中声明,但通过引用转到lambda的内部作用域。问题是你在lambda的参数列表中也有一个名为data(内部作用域)的参数。这导致数据变量从lambda中的外部范围隐藏。

顺便说一下。此外,您的第一个带有函数指针的示例应该被重写,因为内部和外部作用域中的标识符命名也存在冲突。在这种情况下,它并不是很糟糕,因为在内部分数中只有一个数据变量在使用。但是,当参数列表变量和调用函数的外部作用域中的变量具有相同的名称时,这可能会导致程序员混淆,也应该避免。