在C++中,Lambda表达式可以捕获外部作用域中的变量,这样就可以在Lambda表达式的函数体中使用这些变量。捕获可以通过值或引用进行,这两种方式有着不同的行为和用途。
- 值捕获(Value Capture):当一个外部变量被Lambda表达式通过值捕获时,该变量的当前值会被复制到Lambda表达式中。这意味着,即使在Lambda表达式创建后,外部变量的值发生了改变,这个改变也不会影响到Lambda表达式中的值。同样,如果Lambda表达式改变了捕获的变量的值,这个改变也不会影响到外部的变量。
int x = 0;
auto lambda = [x]() { return x+1; }; // x被值捕获
x = 5;
std::cout << lambda() << std::endl; // 输出1,而不是6
- 引用捕获(Reference Capture):当一个外部变量被Lambda表达式通过引用捕获时,Lambda表达式实际上保留了对该变量的引用,而不是复制它的值。这意味着,如果在Lambda表达式创建后,外部变量的值发生了改变,这个改变会影响到Lambda表达式中的值。同样,如果Lambda表达式改变了捕获的变量的值,这个改变也会影响到外部的变量。
int x = 0;
auto lambda = [&x]() { return x+1; }; // x被引用捕获
x = 5;
std::cout << lambda() << std::endl; // 输出6
注意:在使用引用捕获时,需要确保Lambda表达式使用的时候,被捕获的变量仍然存在。如果在Lambda表达式创建后,被捕获的变量已经被销毁,那么在Lambda表达式中使用这个变量将会导致未定义的行为。
这段代码中包含两个Lambda表达式,一个使用引用捕获,另一个使用值捕获。这两个Lambda表达式都会打印变量a、b和c的值,然后增加变量a的值。
-
第一个Lambda表达式使用引用捕获(&),这意味着它会直接操作原始变量a、b和c。在这个Lambda表达式中,它首先打印变量a的值(100),然后打印变量b和c的和(500),然后增加变量a的值。因此,执行这个Lambda表达式后,变量a的值变为101。
-
然后,主程序打印变量a的值,此时a的值为101。
-
第二个Lambda表达式使用值捕获(=),这意味着它会复制变量a、b和c的值,然后在这些复制的值上进行操作。然而,这个Lambda表达式被声明为mutable,这意味着它可以修改捕获的变量的值(在这种情况下,是复制的值,而不是原始的值)。在这个Lambda表达式中,它首先打印变量a的值(101,因为这是在Lambda表达式创建时a的值),然后打印变量b和c的和(500),然后增加变量a的值。但是,因为这是值捕获,所以这个增加不会影响主程序中的变量a。
所以,这段代码的输出应该是:
100 500
101
101 500
注意:这里假设qDebug()
函数的行为类似于C++的std::cout
,即它会打印传递给它的值,然后在值之间添加一个空格,并在每个调用后添加一个换行符
解释它首先打印变量a的值(101,因为这是在Lambda表达式创建时a的值)
在C++中,当你创建一个使用值捕获的Lambda表达式时,它会立即复制所有捕获的变量的当前值。这些复制的值被存储在Lambda表达式中,并在Lambda表达式的函数体中使用。
在你的代码中,第二个Lambda表达式在创建时捕获了变量a、b和c的值。这时,变量a的值是101,因为在第一个Lambda表达式中,a的值被增加了1。因此,当第二个Lambda表达式打印变量a的值时,它打印的是101,这是在Lambda表达式创建时a的值。