本文介绍了C ++ 11 lambda可以捕获文件作用域变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! ISO C ++ 11规范的第5.1.2 p10节规定:这似乎意味着lambda不能捕获文件作用域变量。例如,此程序应该是非法的: #include< iostream& int x = 13; int main() { auto l = [](){return x; }; std :: cout<< l()<< std :: endl; return 0; } 但是, g ++ 4.7.1产生我期望的结果: $ g ++ --version g ++(Ubuntu / Linaro 4.7.2 -2ubuntu1)4.7.2 版权所有(C)2012自由软件基金会,这是免费软件;请参阅复制条件的来源。有NO 保修;甚至不适用于适销性或特定用途的适用性。 $ g ++ -std = c ++ 11 lambda.cpp $ ./a.out 13 但 clang 3.0崩溃: $ clang --version Ubuntu clang版本3.0-6ubuntu3(标签/ RELEASE_30 / final)(基于LLVM 3.0)目标:i386-pc-linux-gnu 线程模型:posix $ clang -std = c ++ 11 lambda.cpp 0 libLLVM-3.0.so.1 0xb70a59e8 1 libLLVM-3.0.so.1 0xb70a5f34 2 0xb775d400 __kernel_sigreturn + 0 3 clang 0x0869f2e9 clang :: Sema :: DeduceAutoType(clang :: TypeSourceInfo *,clang :: Expr *,clang :: TypeSourceInfo *&)+ 73 < snip> ; 我的程序是否违法?如果是非法的,捕获文件范围变量的原因是什么?解决方案 lambda的主体被认为是在lambda表达式的上下文中。也就是说,名称查找就像在lambda之外使用名称一样。参见[expr.prim.lambda] / 7。例如: #include< iostream> int x = 13; int y = 0; int main() { static int y = 42; int z = 1729; auto l = [/ *忘记捕获一会儿* /]() {return x + y + z; }; //找到名字x,y,z,就好像它们在lambda之外被提到了 //找到局部变量y,z和全局x std :: cout return 0; } 现在,您需要存储持续时间。我想这使它有点不容易出错,因为你可以复制和返回lambdas,这样自动变量已被销毁时调用lambda: int main() { static int y = 42; std :: function< int()> F; { int z = 1729; f = [](){return x + y + z; }; //想象我们可以这样做} std :: cout<< f()< std :: endl; //噢哦! return 0; } 当然,对于具有静态存储持续时间的变量,不会出现此问题。 / p> 具体来说,[expr.prim.lambda] / 12说:非自动变量也将通过名称查找找到,但不受此规则的影响。您可以使用它们而不捕捉。 N.B。 odr-use 放松允许使用自动变量来捕获它们,例如: int main() { int x = 42; constexpr int y = 1789; auto l = []() - > int { decltype(x)my_var = 100; // no odr-use of`x` return my_var * y; // no odr-use of`y` }; std :: cout<< l()<< std :: endl; return 0; } Section 5.1.2 p10 of the ISO C++11 specification states:This seems to imply that a lambda cannot capture a file scope variable. For example, this program should be illegal:#include <iostream>int x = 13;int main(){ auto l = [](){ return x; }; std::cout << l() << std::endl; return 0;}However, g++ 4.7.1 produces the result I expect:$ g++ --versiong++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2Copyright (C) 2012 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.$ g++ -std=c++11 lambda.cpp$ ./a.out13But clang 3.0 crashes:$ clang --versionUbuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)Target: i386-pc-linux-gnuThread model: posix$ clang -std=c++11 lambda.cpp0 libLLVM-3.0.so.1 0xb70a59e81 libLLVM-3.0.so.1 0xb70a5f342 0xb775d400 __kernel_sigreturn + 03 clang 0x0869f2e9 clang::Sema::DeduceAutoType(clang::TypeSourceInfo*, clang::Expr*, clang::TypeSourceInfo*&) + 73<snip>Is my program illegal or not? If it is illegal, what is the rationale for the proscription on capturing file scope variables? 解决方案 For purposes of name lookup, the body of the lambda is considered to be in the context of the lambda expression. That is, name lookup happens as if you used the name outside the lambda. See [expr.prim.lambda]/7. For example:#include <iostream>int x = 13;int y = 0;int main(){ static int y = 42; int z = 1729; auto l = [/*forget about the capture for a moment*/]() { return x+y+z; }; // find the names x,y,z as if they had been mentioned outside the lambda // find the locals y, z and the global x std::cout << l() << std::endl; return 0;}Now, you need to capture variables of automatic storage duration. I guess this makes it a bit less error-prone, as you can copy and return lambdas, so that the automatic variables have been destroyed when the lambda is called:int main(){ static int y = 42; std::function<int()> f; { int z = 1729; f = [](){ return x+y+z; }; // imagine we could do this } std::cout << f() << std::endl; // uh-oh! return 0;}Of course, this problem does not appear for variables with static storage duration.Specifically, [expr.prim.lambda]/12 says:Non-automatic variables will be found by name lookup as well, but are not affected by this rule. You can use them without capturing.N.B. the odr-use relaxation allows some uses of automatic variables w/o capturing them, such as:int main(){ int x = 42; constexpr int y = 1789; auto l = []() -> int { decltype(x) my_var = 100; // no odr-use of `x` return my_var*y; // no odr-use of `y` }; std::cout << l() << std::endl; return 0;} 这篇关于C ++ 11 lambda可以捕获文件作用域变量吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-28 01:27