Pits that may be encountered when Lambda is used

Lambda expressions bring a lot of convenience to c++ programming, but when using Lambda, you need to be very careful about the possible problems, familiar with Lambda expressions can smoothly avoid various pits

Reference capture may bring hanging references

This problem is common when a Lambda expression is used to capture a local variable using a reference, and a call to a Lambda expression when the local variable has been cleaned results in a suspended reference to the cleared memory space being captured, for example:

#include "string"
#include "iostream"
#include "functional"

using Func = std::function<void(a) >;Func GetFunc(a) {
  int a = 1;
  return[&] () {std: :cout << a << std: :endl; };
}

int main(int.char* []) {
  std::function<void()> func = GetFunc();
  func();
  return 0;
}
Copy the code

In the above code, a reference to the local variable is captured in the Lambda func expression. After the local block is executed, the end of the local lifecycle is cleaned up, and a reference to the cleaned local variable is used when a call to func is made outside.

This may already be destroyed when caught using this

This problem is similar to the above, capturing this, but it is possible that the object to which this points has been destroyed by the time a Lambda is used, resulting in a suspended reference. For example:

#include "string"
#include "iostream"
#include "functional"

using Func = std::function<void(a) >;class Test {
  public:
    Test(int num): num_(num) {};
    Func GetFunc(a) {
       return[=] () {std: :cout << num_ << std: :endl;
       };
    }
  private:
    int num_;
};

Func GetFunc(a) {
  Test test(1);
  return test.GetFunc();
}

int main(int.char* []) {
  GetFunc()();
  return 0;
}
Copy the code

In the above example, because the local Test object local has been destroyed, the Lambda expression func still holds a reference to that object, resulting in a suspended reference.

An error occurs when capturing the function itself

This error occurs when Lambda expressions recursively call themselves, typically in recursive functions, or recursive callback functions. Because it references itself, the referenced lambda expression may be destroyed some time after creation, causing the captured reference to hang. For example,

#include "string"
#include "iostream"
#include "functional"

volatile bool no_optimize = true; // Prevent the compiler from tuning out errors

using Func = std::function<int(int) >;Func GetFactorialFunc(a) {
  Func fac = [&](int n) -> int {
    return n == 0 ? 1 : n * fac(n- 1);
  };
  if (no_optimize)
    return fac;
  return [] (int n) { return n; };
}

int main(int.char* []) {
  std: :cout << GetFactorialFunc()(10) < <std: :endl;
  return 0;
}
Copy the code

In this example, because the Lambda expression referenced by the regression call is a local variable, it is already recycled at the end of the function, and the recursive call uses a pointing suspension reference, causing an error.