使用Lambda函数重新捕获变量是否合法?

时间:2016-01-21 14:23:39

标签: c++ c++11 language-lawyer

编写此类代码是否正确:

class A
{
private:
    int m_int;

public:
    void foo()
    {
        int a = 1;
        int b = 2;
        int c = 3;
        float f = 3.14f;
        std::string s("Something");

        const auto f1 = [=] ()
        {
            // use only a, b, c
            int d = a + b + c;

            const auto f2 = [=] 
            {
                // use f, s and also d
                std::cout << f << s << d ;
            }
        };
    }
};

问题是内部lambda使用了一些外部不需要的变量。如果这是无效的,那我应该怎么写?

注意:我也可以捕获指针变量。因此,abcfs也可以成为指针。

4 个答案:

答案 0 :(得分:4)

有问题的代码(尽管内部lambda声明中的拼写错误)是正确的。由于第一个lambda将从封闭函数中捕获所有内容,因此第二个lambda将通过“捕获全部”封闭的lambda来访问它。

答案 1 :(得分:2)

根据C ++标准(5.1.2 Lambda表达式)

  

9一个lambda表达式,其最小的封闭范围是块范围   (3.3.3)是局部lambda表达式;任何其他lambda表达式   不应该有捕获默认或简单捕获   λ-介绍人。本地lambda表达式的范围是   封闭范围的集合,包括最里面的   封闭功能及其参数。 [注意:此范围   包括任何介入的lambda表达式。 - 后注]

因此第二个lambda的到达范围是成员函数foo()的范围。由于lambda表达式具有默认捕获,因此它可以捕获此范围内的局部变量。

同样重要的是要注意同一部分第13段的以下部分

  

13 ...如果lambda表达式捕获实体并且该实体是   未在紧邻的lambda表达式中定义或捕获   或功能,该程序是不正确的。

在您的示例中,封闭的lambda使用默认捕获从函数块作用域隐式捕获内部lambda的所有必需变量。

答案 2 :(得分:0)

引自http://en.cppreference.com/w/cpp/language/lambda

  

[=]捕获在体内使用的所有自动变量   lambda by value

因为您在foo中捕获了 f1的所有变量,所以在f2中使用它们没有问题。

所以它是有效的,尽管你可能想考虑通过引用来捕获它们。

答案 3 :(得分:0)

这将有效,因为您通过键入 [=] 按值捕获所有局部变量。因此f,s和d将在f2中可见,但它只是副本,而不是实际变量