我对captures
中capture-list
的行为感到困惑。
#include <iostream>
using namespace std;
int main()
{
int a = 1, b = 1, c = 1;
auto m = [a, &b, &c]() mutable
{
std::cout << a << b << c << '\n'; // prints 122
a = 3; b = 3; c = 3;
};
a = 2; b = 2; c = 2;
m();
std::cout << a << b << c << '\n'; // prints 233
}
输出:
122
233
如果lambda函数在另一个函数内声明:
auto m1 = [a, &b, &c]() mutable
{
auto m2 = [a, b, &c]() mutable
{
std::cout << a << b << c << '\n';
a = 4; b = 4; c = 4;
};
a = 3; b = 3; c = 3;
m2();
};
据我所知,
by-copy
捕获初始化为其当前值。by-reference
在调用函数时初始化捕获。by-copy
捕获不会影响其阻止。by-reference
捕获可以更改其原始值。我是对的吗?我已经学过,但我没有明白。任何人都可以解释一下吗?
答案 0 :(得分:2)
在这个lambda表达式中
auto m = [a, &b, &c]() mutable
{
std::cout << a << b << c << '\n'; // prints 122
a = 3; b = 3; c = 3;
};
创建的对象有自己的a
副本。定义对象时,变量a
的值为1。
对于另外两个变量,该对象包含引用。
您可以通过以下方式想象lambda表达式
int a = 1, b = 1, c = 1;
class Unnamed
{
private:
int a;
int &b;
int &c;
public:
Unnamed( int a, int &b, int &c ) : a( a ), b( b ), c( c )
{
}
void operator ()()
{
std::cout << a << b << c << '\n'; // prints 122
a = 3; b = 3; c = 3;
}
} m( a, b, c );
因此,lambda对象定义之后a
的任何更改都不会影响对象的相应数据成员。但是,当变量b
和c
被更改时,对象的相应运算符函数的输出将反映这些变化。
所以在这些陈述之后
a = 2; b = 2; c = 2;
此次电话
m();
将输出由变量a
的前一个值初始化的对象的自己的数据成员的值以及b
和c
的当前值,因为它包含对这些的引用变量
所以输出是
122
第二个输出
std::cout << a << b << c << '\n';
反映了变量a
,b
和c
的当前值2,3和3,因为在前面调用lambda变量b
和c
已被更改。所以你得到了
233
答案 1 :(得分:2)
lambda实际上只是功能对象的语法糖。您的代码等同于
int main()
{
int a = 1, b = 1, c = 1;
struct {
int a;
int& b;
int& c;
void operator()()
{
std::cout << a << b << c << '\n'; // prints 122
a = 3; b = 3; c = 3;
}
} m{a, b, c};
a = 2; b = 2; c = 2;
m();
std::cout << a << b << c << '\n'; // prints 233
}
这不是严格的解释。如果Lambda没有捕获,则可以将其转换为函数指针。但在特定的例子中,这是正确的