use*_*157 5 c++ gcc clang c++11 gcc4.8
#include<iostream>
using namespace std;
int main()
{
const int k = 10;
// Capture k by value
auto myl = [k] (int k) { cout << " ++k=" << ++k ; };
myl(k+10);
}
Run Code Online (Sandbox Code Playgroud)
错误如下
lamda.cpp: In lambda function:
lamda.cpp:10:50: error: increment of read-only variable âkâ
auto myl = [k] (int k) { cout << " ++K=" << ++k ; };
Run Code Online (Sandbox Code Playgroud)
显然我所指的是局部变量K而不是const成员K.
这并不像看起来那么简单。通过复制捕获的 lambdak主要相当于一个结构对象,其闭包类型具有名为 的成员k,并且operator()其定义使用指定的参数和主体。如果这在技术上是正确的,那么我们肯定知道函数参数隐藏了类成员。
但标准实际上并不是这样定义 lambda 的。相反,它表示通过值捕获的任何实体都对应于闭包类型的未命名成员。在 lambda 主体中,名称查找在 lambda 的封闭范围中查找,而不是在闭包类型的范围中查找。如果该名称查找找到由副本捕获的实体,则编译器必须在内部将该名称的用法转换为未命名成员的用法。在 C++11 和 C++14 中,这些规则没有明确指定 lambda 参数名称如何适合该名称查找方案,因此,不同的编译器和编译器版本在此类情况下的行为不一致捕获的实体和 lambda 参数具有相同的名称。
通过缺陷解决方案 2211,C++17 通过使其非法来解决了该问题:
[expr.prim.lambda.capture]/5:
如果simple-capture中的标识符显示为lambda-declarator的parameter-declaration-clause的参数的declarator-id,则该程序格式错误。[例子:
Run Code Online (Sandbox Code Playgroud)void f() { int x = 0; auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name }--结束示例]
(另请参阅当前草案镜像中的同一段落。)