我对this C++ weekly中的一个片段感到惊讶。
我在这里复制了我不理解的部分:
int main() {
auto accumulator = [sum = 0](int value) mutable {
sum += value;
return sum;
};
accumulator(1); // expected return value: 1
accumulator(2); // expected return value: 1+2
return accumulator(-1); // expected return value: 1+2-1
}
隐含的期望(在注解中)得到满足,但我不认识这个捕获语法:sum在lambda声明作用域中不存在,所以它不能捕获它。
我知道这种语法:[lhs = rhs](whatever){whatever_again};
,在闭包中声明一个lhs
变量,该变量在声明时由声明范围中的rhs
值初始化。这段代码可以工作的事实似乎意味着:
- 如果没有声明所请求的捕获变量,则捕获实际上是一个定义;
- 调用之间的值的持久性,意味着
sum
实际上是lambda闭包的成员; sum
不是const,因为lambda是可变的。
然而,我无法将这些假设与lambda cppreference相匹配。
我知道这种语法:[lhs = rhs](whatever){whatever_again};
,在闭包中声明一个lhs
变量,该变量在声明时由声明范围中的rhs
值初始化。上面的行为似乎表明rhs
可以仅仅是一个值,而lhs
的实际类型是自动推导出来的(我想我是从下面的ClosureType::Captures中得到这一点的)。* * 我的理解是否正确?有人能指出一个参考或解释cppreference的措辞吗?**
我担心它会引发第二个问题,这可能是一个重复的问题(请填写免费告诉我,或者要求我将帖子拆分为2):* * 如何确定lambda体中变量的类型?**
备注
来自ClosureType::捕获:lambda body中的类型。
每个数据成员的类型是对应的捕获实体的类型,除非实体具有引用类型(在这种情况下,对函数的引用被捕获为对被引用函数的左值引用,对对象的引用被捕获为被引用对象的副本)。
ClosureType::Captures:闭包非静态成员变量:
闭包类型包括以未指定的顺序声明的未命名的非静态数据成员,其保持如此捕获的所有实体的副本。
恕我直言,如果我将 * entity * 概念从lvalue
扩展到任何类型的值,我的假设都可能是正确的。
1条答案
按热度按时间w1jd8yoj1#
隐含的期望(在注解中)得到满足,但我不认识这个捕获语法:
sum
不存在于lambda声明作用域中,因此它无法捕获它。sum
不需要。sum
不是我们要捕获的实体的名称,它只是捕获子句中的一个名称,它是lambda的数据成员的别名,我们可以在调用操作符中使用它。只有当sum
没有初始化器时,sum
才是被捕获实体的名称。这个特性(带有初始化器的capture子句)被称为 Generalized Captures。如果我们将上面的代码片段转换为“引擎盖下”发生的事情,那么它将更有意义:
您可以看到捕获子句中的
[sum = 0]
仅仅意味着闭包类型中有一个类型为int
的成员。每个数据成员的类型都是对应的捕获实体的类型,除非该实体具有引用类型。
在本例中,捕获的实体是临时对象
0
,其类型为int
,因此我们的数据成员也是int
类型。标签:Your code on cppinsights.io