C++ lambda 表达式中的捕获和参数有什么区别?

What is the difference between captures and parameters in a C++ laambda expression?

https://en.cppreference.com/w/cpp/algorithm/sort

  std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
 
    auto print = [&s](std::string_view const rem) {
        for (auto a : s) {
            std::cout << a << ' ';
        }
        std::cout << ": " << rem << '\n';
    };
 
    std::sort(s.begin(), s.end());
    print("sorted with the default operator<");
 

例如,在这段代码中,为什么捕获“s”和参数“使用默认运算符<排序”? 为什么捕获“使用默认运算符<”而不是参数“s”排序?

捕获的值保留在 lambda 对象中,而函数参数仅用于调用。与任何函数一样,您可以多次调用 lambda 函数,每次调用其参数列表都有不同的参数列表。然而,lambda 对象恰好构造一次,此时捕获绑定到 lambda 的内部成员。

如果您将代码放入 https://cppinsights.io,您就会了解编译器如何处理您的 lambda 函数:

  std::array<int, 10> s = {{5, 7, 4, 2, 8, 6, 1, 9, 0, 3}};
    
  class __lambda_7_18
  {
    public: 
    inline /*constexpr */ void operator()(const std::basic_string_view<char, std::char_traits<char> > rem) const
    {
      {
        std::array<int, 10> & __range1 = s;
        int * __begin1 = __range1.begin();
        int * __end1 = __range1.end();
        for(; __begin1 != __end1; ++__begin1) {
          int a = *__begin1;
          std::operator<<(std::cout.operator<<(a), ' ');
        }
        
      }
      std::operator<<(std::operator<<(std::operator<<(std::cout, ": "), std::basic_string_view<char, std::char_traits<char> >(rem)), '\n');
    }
    
    private: 
    std::array<int, 10> & s;
    
    public:
    __lambda_7_18(std::array<int, 10> & _s)
    : s{_s}
    {}
    
  };
  
  __lambda_7_18 print = __lambda_7_18{s};
  print.operator()(std::basic_string_view<char, std::char_traits<char> >("sorted with the default operator<"));

如您所见,您的 print lambda 是一个包含对捕获数组的引用的对象:s。当您调用它时,它的 operator() 成员函数会用您传递给它的参数调用,这里是一个 std::string_view 和值 "sorted with the default operator<"。您可以使用不同的值再次调用它。

lambda 不是函数,它是 class 带有将您的参数作为参数的 operator() 的函数。因此,捕获的变量将成为 class 的成员,因此可以重复使用,参数将成为运算符的参数。