Lambda的成员是如何初始化的?

时间:2019-09-16 00:13:57

标签: c++11 lambda

据说,lambda的成员是在定义lambda时初始化的,而不是在创建该lambda的对象时初始化的。为了进一步理解这一点,我制作了一个函数foo,该函数打印一条简单的消息(稍后检查),并返回一个用于初始化lambda成员的整数值(任意值,此处为1024)。

在lambda主体内部,它会打印其捕获对象的值。

int foo() {
    std::cout << "foo()" << std::endl;
    return 1024;
}

int main() {

    int x = 0;
    [x = foo()]()mutable{ x = foo();  cout << "in un-named lambda x: " << x << endl; };
}

输出:

foo()

为什么我只有foo()却没有得到

foo()
foo()
in un-named lambda x: 1024
  • 这是否意味着[x = foo()]是初始化并且在{x = foo()}中是赋值?

1 个答案:

答案 0 :(得分:5)

因此,您的代码有几个问题:

  • int x = 0;

    x从未使用过。见下文

  • [x = foo()]

    这不会捕获x中的变量main。而是a generalized lambda capture。如果要考虑与lambda等效的类类型的术语,它将创建一个名为x的成员,该成员初始化为foo()。再次与main中的变量x完全没有联系。

  • [x = foo()]()mutable{ x = foo(); cout << "in un-named lambda x: " << x << endl; };

    最后,您的lambda永远不会被调用。因此,{ x = foo(); cout << "in un-named lambda x: " << x << endl; }永远不会执行。

有一个很棒的工具,可让您查看编译器对代码的转换方式:https://cppinsights.io/s/cd26f632

#include <iostream>

int foo()
{
  std::operator<<(std::cout, "foo()").operator<<(std::endl);
  return 1024;
}


int main()
{
  int x = 0;

  class __lambda_12_5
  {
    int x;
    public: 
    inline /*constexpr */ void operator()()
    {
      x = foo();
      std::operator<<(std::cout, "in un-named lambda x: ").operator<<(x).operator<<(std::endl);
    }

    public: __lambda_12_5(int _x)
    : x{_x}
    {}

  } __lambda_12_5{foo()};

  ;
}

还请启用并注意您的警告:Why should I always enable compiler warnings?

source>:12:5: warning: expression result unused [-Wunused-value]

    [x = foo()]()mutable{ x = foo();  std::cout << "in un-named lambda x: " << x > << std::endl; };

    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~> ~~~~~~~~~~

<source>:11:9: warning: unused variable 'x' [-Wunused-variable]

    int x = 0;

        ^

2 warnings generated.

如您所见,您将被告知未使用的变量和未调用的lambda。