是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。
1,指针函数是指返回值是指针的函数,即本质是一个函数。我们知道函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。
2,函数指针的本质是一个指针,该指针的地址指向了一个函数,所以它是指向函数的指针。我们知道,函数的定义是存在于代码段,因此,每个函数在代码段中,也有着自己的入口地址,函数指针就是指向代码段中函数入口地址的指针。
事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。
int PtrFuction()
{
cout << "PtrFuction---------------";
return 100;
}
int PtrFuction_2(int x ,int y)
{
cout << "PtrFuction_2---------------";
return x*y;
}
cout << (PtrFuction) << endl;
cout<< (*PtrFuction)<<endl;
cout << (&PtrFuction)<<endl;
cout << (PtrFuction)() << endl;
cout << (*PtrFuction)() << endl;
cout << (&PtrFuction)() << endl;
//000000013F891D4D
//000000013F891D4D
//000000013F891D4D
//PtrFuction-------------- - 100
//PtrFuction-------------- - 100
//PtrFuction-------------- - 100
甚至可以用数组存放
int(*Array[])(void) = { PtrFuction,PtrFuction,PtrFuction };
cout << Array[1]<<" " << Array[1]() << endl;
vector<int(*)()> Array2(5, PtrFuction);
cout << Array2[1]<<" "<< Array2[1]() << endl;
通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
假设A随机的是个时间会给B发一个数据,但是不知道是什么时候,这时候有两个方案
1,B每隔一段时间去查找是否获得这个数据,主动权在B。
2,A在发信息的时候调用B,主动权在A。
因为不知道A什么时候发数据,所以方法一不可行。
当需要执行一个任务而,但是不确切是什么时候
把需要的事件封装成函数,再把这个函数和某一时间或者事件,中断建立关联。
当需要的时候,回调函数会被执行。
不需要等到需要调用这个函数的时候在调用它。
int PtrFuction_2(int x ,int y)
{
cout << "PtrFuction---------------" << endl;
return x*y;
}
typedef int(*PtrFun)(int,int); //定义一个函数指针类型
void CallPtr(PtrFun PtrFuction_2,int x = 1,int y = 1)
{
cout << "执行回调函数---------------" << endl;
int Ans = PtrFuction_2(x, y);
cout << "结束回调函数---------------" << endl;
}
CallPtr(PtrFuction_2);
CallPtr(PtrFuction_2,3);
CallPtr(PtrFuction_2,3,2);
//同步的执行
1,回调可以是同步也可以是异步
2,同步可以是单线程也可以是多线程
3, 异步必须是多线程或多进程(每个进程可以是单线程) ,异步必须依靠多线程或多进程才能完成。
同步毁掉:A要等B执行完才能继续。
异步回调:A不需要等B,A继续执行,B独自执行。
异步调用:
#include
#include
#include
#include
using namespace std;
typedef void(*PtrCallBack)(int x);
struct Parameter
{
int i;
PtrCallBack CallBck;//函数指针
Parameter(int i, PtrCallBack CallBck) :i(i), CallBck(CallBck) {};
};
void CallBack_thread(Parameter* p)
{
Parameter* p1 = (Parameter*)p;
Sleep(600);
p1->CallBck(p1->i);//执行B
}
void SetCallBack(int i, PtrCallBack CallBck)
{
cout << "A开始了" << endl;
Parameter* p = new Parameter(i, CallBck);
thread th(CallBack_thread,p);
cout << "A结束了" << endl;
th.detach();
}
void CallBck(int i)
{
cout << "B开始了" << endl;
cout << i << endl;
Sleep(600);
cout << "B结束了" << endl;
}
int main()
{
SetCallBack(456, CallBck);
}
函数直接或间接调用函数本身,则该函数称为递归函数。递归函数不能定义为内联函数。
如下,这是LeetCode上一道简单难度的镜像二叉树的题目,可以看到isSymmetric(TreeNode* root)
一直再调用自身。
递归的底层实现其实是一个栈。栈的特点是**后进先出,**也就是最后进入栈的事件是最先被处理的,递归到最内层(到退出条件),开始从内层向外逐层调用函数自己计算处理。
优点:使用递归时,常常可以让代码更加简洁
缺点:递归会占用比较多的内存,当递归次数比较多时,性能就会降低
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return IsSame(root, root);
}
bool IsSame(TreeNode* l1, TreeNode* l2)
{
if (l1 == nullptr && l2 == nullptr)
{
return true;
}
if (l1 == nullptr || l2 == nullptr)
{
return false;
}
return (l1->val == l2->val)
&& IsSame(l1->right, l2->left)
&& IsSame(l1->left, l2->right);
}
};