我正在处理一些带有一些数据的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;
但我认为一个空的捕获组会在查找期间排除第一个实例化。
这个警告合法吗?
为什么空捕获不足以避免警告?
答案 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中的外部范围隐藏。