Why does std::function still need function pointer in C++?

In C/C++, pointers can be used to point to a piece of code. This pointer is called a function pointer. Suppose there is such a piece of code:

#include <stdio.h>

int func(int a) {
    
    
  return a + 1;
}

void main() {
    
    
   int (*f)(int) = func;
   printf("%p\n", f);
}

We define a function func, then use the pointer variable f to point to the function, and then print out the address pointed to by the variable f. The code is very simple, and then we compile it and look at the instructions generated after compilation. We focus on the func function:

0000000000400526 <func>:
  400526:       55                      push   %rbp
  400527:       48 89 e5                mov    %rsp,%rbp
  40052a:       89 7d fc                mov    %edi,-0x4(%rbp)
  40052d:       8b 45 fc                mov    -0x4(%rbp),%eax
  400530:       83 c0 01                add    $0x1,%eax
  400533:       5d                      pop    %rbp
  400534:       c3                      retq

It can be seen that the compiled function func is located at the address 0x400526, let us remember this address.

Then run the compiled program and think about what this code will output?

Obviously it should be the address of the func function in memory!

$ ./a.out
0x400526

You guessed it right, in fact, the function pointer is also a pointer in essence, but what this pointer points to is not a piece of data in the memory but a piece of code in the memory, just like this: see, the pointers we often say are
insert image description here
generally It points to a piece of data in the memory, and the function pointer points to a piece of code in the memory. In this example, it points to the memory address 0x400526, where the machine instruction of the function func is stored. Now you should understand the function pointer.

The function of the function pointer is to pass a piece of code as a variable. One of the main uses is the callback function.

The callback function is actually defined in module A and called in module B, like this:
insert image description here
However, sometimes we have such a scenario, we still need to define a function in module A, and the operation of function A needs to rely on the data generated by module B , and then pass the function defined by module A and the data generated by module B to the C module to call, just like this: At
insert image description here
this time, the simple function pointer is not enough, because the function pointer simply points to the memory. A piece of code, we not only need to pass a piece of code in the memory but also a piece of data in the memory to module C, at this point you can define a structure to package the code and data, like this:

typedef void (*func) (int);

struct closure{
    
    
  func f;
  int arg;    
};

We named this structure closure, notice that there are two parts in this structure:

A pointer variable pointing to the code
A variable storing data
In this way, we assign a value to the pointer variable in module A, assign a value to the variable storing data in module B, and then pass this structure to module C, which can be used in this way:

void run(struct functor func) {
    
    
    func->f(func->arg);
}

That is to say, the closure contains both a piece of code and the data used by this code. The data here is also called context, that is, the context, or the environment, that is, the environment. No matter how you call it, it is actually the data that the function depends on: and insert image description here
this It is also the purpose of std::function in C++.

Simple function pointers do not have the ability to capture the context. The context here refers to the data that the code depends on. You have to construct a structure by yourself to store the context that the code depends on.

In C++, you can't simply use the function pointer to point to the member function of the object, because the function pointer has no way to capture the context of this (pointer to the object).

The role of std::function is essentially not much different from the structure we just defined.

Using std::function, you can not only save a piece of code, but also save the necessary context, and then call this code based on the context at the appropriate place.

At the same time, std::function is more general, you can use it to store any callable object (callable object), as long as it has the correct function signature.

Guess you like

Origin blog.csdn.net/C214574728/article/details/127026324