C++ 返回捕获局部变量的lambda
今天,我在C++11lambdas中遇到了一个非常不直观的行为(至少对我来说是这样)。有关守则如下:C++ 返回捕获局部变量的lambda,c++,c++11,lambda,currying,C++,C++11,Lambda,Currying,今天,我在C++11lambdas中遇到了一个非常不直观的行为(至少对我来说是这样)。有关守则如下: #include <stdio.h> auto sum(int x) { return [&x](int y) { return x + y; }; } int main() { int a = sum(2)(3); printf("%d\n",a); } #包括 自动求和(整数x){ 返回[&x](整数y){ 返回x+y
#include <stdio.h>
auto sum(int x) {
return [&x](int y) {
return x + y;
};
}
int main() {
int a = sum(2)(3);
printf("%d\n",a);
}
#包括
自动求和(整数x){
返回[&x](整数y){
返回x+y;
};
}
int main(){
int a=和(2)(3);
printf(“%d\n”,a);
}
不是打印5,而是打印乱七八糟的内容。实际上,至少在我的GCC版本中,如果我打开-O2优化标志,它实际上会打印5。由于输出取决于编译器的优化级别,因此它是未定义的行为。过了一会儿,我想我明白发生了什么
当调用函数sum时,与参数x相对应的堆栈变量被设置为2,然后函数sum返回,编译器在那里执行以下代码所需的任何内容都可能会覆盖此堆栈变量,并且当lambda最终执行时,x所在的位置不再包含2,程序将3加到任意整数上
C++中有没有一种优雅的方法来保证变量正确捕获?
<代码> int x/COD>生命有限。对自动存储变量(您称之为“堆栈”)的引用仅在变量的生存期内有效。在这种情况下,只有在变量所在的堆栈帧(作用域)或函数的函数参数结束之前
[&]
通过引用捕获任何提到的(“本地”)变量,但此
除外(如果使用或隐式使用,则通过值捕获)<代码>[=]按值捕获任何提到的变量[x]
将显式地捕获x
,并显式地通过引用捕获[&x]
。在C++17中,[*这个]
也可以工作
还有[x=std::move(x)]
,或[blah=expression]
通常,如果lambda将超过当前范围,则不要使用
[&]
:明确说明捕获的内容。int x
的生存期有限。对自动存储变量(您称之为“堆栈”)的引用仅在变量的生存期内有效。在这种情况下,只有在变量所在的堆栈帧(作用域)或函数的函数参数结束之前
[&]
通过引用捕获任何提到的(“本地”)变量,但此
除外(如果使用或隐式使用,则通过值捕获)<代码>[=]按值捕获任何提到的变量[x]
将显式地捕获x
,并显式地通过引用捕获[&x]
。在C++17中,[*这个]
也可以工作
还有[x=std::move(x)]
,或[blah=expression]
一般来说,如果lambda将超过当前范围,请不要使用
[&]
:明确说明捕获内容。按值捕获[=]
。谢谢!这比我想象的要简单得多。对于读者来说,这是C++14,而不是C++11。函数返回值的类型推断是在C++14中添加的。我使用g++-std=C++11进行编译,从--version的输出来看,它似乎是从2013年开始的。也许这是针对C++11的GCC的非标准扩展?我认为这是GCC的一个扩展,不应该使用严格的编译器flagsCapture by value[=]
。谢谢!这比我想象的要简单得多。对于读者来说,这是C++14,而不是C++11。函数返回值的类型推断是在C++14中添加的。我使用g++-std=C++11进行编译,从--version的输出来看,它似乎是从2013年开始的。也许这是针对C++11的GCC的非标准扩展?我认为这是对GCC的扩展,不应该允许使用严格的编译器标记来详细说明答案。我在Currimon C++上看到的大多数答案都有很多模板代码,我无法理解,所以我刚开始尝试。现在我更清楚我在做什么了。谢谢你详尽的回答。我在Currimon C++上看到的大多数答案都有很多模板代码,我无法理解,所以我刚开始尝试。现在我更清楚我在做什么了。