Post

c++的lambda捕获-02

单纯记录一点东西,代码都是cpp insight生成的

代码大概是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cstdio>
#include <iostream>

using namespace std;

struct test{
  int id_ = 0;
  auto get() {
  	auto func = [=]() {
    	cout << id_ << '\n';
   	};
    return func;
  }
};


int main()
{
  test t;
  auto res = t.get();
}

等价于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <cstdio>
#include <iostream>

using namespace std;

struct test
{
  int id_ = 0;
  inline __lambda_9_16 get()
  {
        
    class __lambda_9_16
    {
      public: 
      inline /*constexpr */ void operator()() const
      {
        std::operator<<(std::cout.operator<<(__this->id_), '\n');
      }
      
      private: 
      test * __this;
      public: 
      // inline /*constexpr */ __lambda_9_16(__lambda_9_16 &&) noexcept = default;
      __lambda_9_16(test * _this)
      : __this{_this}
      {}
      
    };
    
    __lambda_9_16 func = __lambda_9_16{this} /* NRVO variable */;
    return func;
  }
  
  // inline constexpr test() noexcept = default;
};


int main()
{
  test t = test();
  __lambda_9_16 res = t.get();
  return 0;
}

这个是c++20以前的,=还是会默认捕获this,20开始这个就编译不过了,会默认不捕获this。如果有同名变量在局部的话,实测会优先捕获局部的。

比如,局部放一个id_ = 1, 生成的代码类似

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct test
{
  int id_ = 0;
  inline __lambda_10_16 get()
  {
    int id_ = 1;
        
    class __lambda_10_16
    {
      public: 
      inline /*constexpr */ void operator()() const
      {
        std::operator<<(std::cout.operator<<(id_), '\n');
      }
      
      private: 
      int id_;
      public: 
      // inline /*constexpr */ __lambda_10_16(__lambda_10_16 &&) noexcept = default;
      __lambda_10_16(int & _id_)
      : id_{_id_}
      {}
      
    };
    
    __lambda_10_16 func = __lambda_10_16{id_} /* NRVO variable */;
    return func;
  }
  
  // inline constexpr test() noexcept = default;
};

另外msvc有一个bug

1
2
3
4
5
6
7
struct S {
  static void Method();
  void Method(int x);
  void Test() {
    auto f = [/*this*/] { S::Method(); };
  }
};

这里一定要带一个this,不然会有warning,这个是msvc的一个bug,修复在vs2019直接带上

  1. /Zc:lambda
  2. /std:c++latest

虽然理论上他解析出来的应该类似是下面的,应该不需要this的才是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct S
{
  static void Method();
  
  void Method(int x);
  
  inline void Test()
  {
        
    class __lambda_10_14
    {
      public: 
      inline /*constexpr */ void operator()() const
      {
        Method();
      }
      
      using retType_10_14 = auto (*)() -> void;
      inline constexpr operator retType_10_14 () const noexcept
      {
        return __invoke;
      };
      
      private: 
      static inline /*constexpr */ void __invoke()
      {
        __lambda_10_14{}.operator()();
      }
      
      
    };
    
    __lambda_10_14 f = __lambda_10_14{};
  }
  
};
This post is licensed under CC BY 4.0 by the author.

Trending Tags