C++ lambda捕获变量的规则

C++ lambda捕获变量的规则,c++,visual-c++,lambda,c++11,g++,C++,Visual C++,Lambda,C++11,G++,例如: class Example { public: explicit Example(int n) : num(n) {} void addAndPrint(vector<int>& v) const { for_each(v.begin(), v.end(), [num](int n) { cout << num + n << " "; }); } private: int num; };

例如:

class Example
{
public:
    explicit Example(int n) : num(n) {}
    void addAndPrint(vector<int>& v) const
    {
        for_each(v.begin(), v.end(), [num](int n) { cout << num + n << " "; });
    }
private:
    int num;
};

int main()
{
    vector<int> v = { 0, 1, 2, 3, 4 };

    Example ex(1);
    ex.addAndPrint(v);
    return 0;
}
类示例
{
公众:
显式示例(intn):num(n){}
无效添加和打印(矢量和v)常量
{

对于每个(v.begin(),v.end(),[num](int n){cout标准规定如下(5.1.2):

使用非限定名称查找的常规规则(3.4.1)查找捕获列表中的标识符;每个 此类查找应找到一个变量,该变量的自动存储持续时间声明在本地文件的到达范围内 lambda表达式

据我所知,GCC编译器是正确的,因为“num”在lambda声明点处于到达范围内。

5.1.2/9:

局部lambda表达式的到达范围是 封闭范围包括最里面的封闭函数 及其参数

和5.1.2/10:

捕获列表中的标识符是使用常规规则查找的 对于非限定名称查找(3.4.1);每次此类查找应找到一个 变量中声明了自动存储持续时间 局部lambda表达式的作用域


由于
num
既没有在任何函数作用域中声明,也没有自动存储持续时间,因此无法捕获。因此VS是对的,g++是错的。

请注意,您必须在此处通过值捕获
this
,而不是
num
。当您使用
num
时,实际上是在使用
this->num
。还请注意,MSVC没有实现lambdas的C++11措辞,因为它在2008年实现所有这些之后发生了变化。@Alexandre:捕获
this
实际上与通过引用捕获
num
是一样的。这似乎不是这里想要的。@Ben:很好。但是这里的结果是一样的,因为闭包没有逃逸
 addAndPrint
的范围(无论如何,整个内容都可能在这里内联).5.1.2正如@dimitri引用的那样,似乎表明MSVC是正确的,因为
num
不是一个具有自动存储持续时间的变量。然而,这种行为非常奇怪。它不足以在范围内,它必须是一个具有自动存储持续时间的变量。感谢您的澄清。我发现g++4.6.2在ng捕获,例如,
[=,this]
也进行编译,他们计划在4.7.0中修复它们。