文章

复习:std::function 用法笔记

std::function 可以将函数,函数对象(仿函数),lambda表达式包装成一个对象std::function对象本身可以作为函数参数,并且是可复制的(复制构造、赋值)。

1. 封装函数指针

1
2
3
4
5
6
7
8
int add(int a, int b) { return a + b; }

int main() {
  std::function<int(int, int)> f = add;
  int result = f(1, 2);
  std::cout << result << std::endl;
  return 0;
}

2. 封装函数对象(仿函数)

1
2
3
4
5
6
7
8
9
10
11
struct Adder {
  int operator()(int a, int b) { return a + b; }
};

int main() {
  Adder adder;
  std::function<int(int, int)> f = adder;
  int result = f(1, 2);
  std::cout << result << std::endl;
  return 0;
}

3. 封装 lambda 表达式

1
2
3
4
5
6
7
int main() {
  // using func_t = int(int, int);
  std::function<int(int, int)> f = [](int a, int b) { return a + b; };
  int result = f(1, 2);
  std::cout << result << std::endl;
  return 0;
}

4. 与 std::bind 结合使用

1
2
3
4
5
6
7
8
int add(int a, int b) { return a + b; }

int main() {
  std::function<int(int)> f = std::bind(add, 1, std::placeholders::_1);
  int result = f(2);
  std::cout << result << std::endl;
  return 0;
}

5. lambda 表达式

lambda表达式是一个匿名函数对象,即编译器会创建一个仿函数( 调用时,调用 operator()(....) ),并将外部捕获的变量,添加到该匿名对象中。这些是lambda的额外开销。

注:在O2编译时,仿函数也会被优化掉,直接编译成跳转代码段。

1
2
3
4
5
6
7
8
9
10
11
int main()
{
  // Lambda & auto
  int member=10;
  auto endGame = [=](int a, int b){ return a+b+member;};

  endGame(4,5);

  return 0;

}

展开成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
  int member = 10;

  class __lambda_6_18
  {
    int member;
    public: 
    inline /*constexpr */ int operator()(int a, int b) const
    {
      return a + b + member;
    }

    public: __lambda_6_18(int _member)
    : member{_member}
    {}

  };

  __lambda_6_18 endGame = __lambda_6_18{member};
  endGame.operator()(4, 5);

  return 0;
}

参考

本文由作者按照 CC BY 4.0 进行授权