在C ++中,您可以像这样声明lambda:
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << '\n'; };
auto b = [&]() { ++x; std::cout << x << '\n'; };
两者都让我修改x
,所以有什么区别?
Answers:
第一个只会修改自己的副本,x
而外部不会x
更改。第二个将修改外部x
。
尝试以下各项后添加打印语句:
a();
std::cout << x << "----\n";
b();
std::cout << x << '\n';
预计将打印:
6
5
----
6
6
考虑一下lambda可能会有所帮助
表达式提供了一种创建简单函数对象的简洁方法
(请参阅标准的[expr.prim.lambda])
他们有
[...]公共内联函数调用运算符[...]
声明为const
成员函数,但仅
[...]当且仅当lambda表达式的参数声明子句后没有
mutable
你可以想到
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << '\n'; };
==>
int x = 5;
class __lambda_a {
int x;
public:
__lambda_a () : x($lookup-one-outer$::x) {}
inline void operator() { ++x; std::cout << x << '\n'; }
} a;
和
auto b = [&]() { ++x; std::cout << x << '\n'; };
==>
int x = 5;
class __lambda_b {
int &x;
public:
__lambda_b() : x($lookup-one-outer$::x) {}
inline void operator() const { ++x; std::cout << x << '\n'; }
// ^^^^^
} b;
问:但是如果它是一个const
函数,为什么我仍然可以更改x
?
答:您只是在改变外面x
。lambda本身x
是一个引用,并且该操作++x
不会修改reference,而是引用的值。
之所以可行,是因为在C ++中,指针/引用的常量不会更改通过它看到的指针/引用的常量。
const
实际上没有什么区别。您总是通过引用对引用对象进行变异。再举一个例子:int main () { int x; auto a = [=]() { ++x; }; }
。g ++将为此给出一条错误消息,因为这[=]
意味着生成的函数对象获得了自己的成员变量x
,但是缺少mutable
意味着生成了const
成员函数调用运算符的功能,因此x
不能分配。
auto c = [=]() { ++x; };
上面加上这种情况将更清楚地说明为什么mutable
和const
会有所不同。
mutable
资格默认情况下,const
规范应该是明确的。
a
一些你想要的地方b
。而且您的匿名类类型的对象没有初始化程序。可能想解释一下我们假装lambda_a()
是一个构造函数,尽管该类没有名称。