函数指针正确声明为int (*func_ptr)(int, int),星号与名称必须括起;赋值时函数名自动退化为指针;调用前须判空并确保签名严格匹配;std::function用于lambda、成员函数等灵活场景,原生指针适用于高性能确定场景。

函数指针声明怎么写才不报错
最常出错的是括号位置——int (*func_ptr)(int, int) 是对的,int *func_ptr(int, int) 是错的(这其实是函数声明,返回 int*)。关键在星号和函数名必须用括号包住,否则编译器按优先级解析成“返回指针的函数”。
- 左边类型是函数返回值(如
int),右边是参数列表(如(int, int)),中间(*func_ptr)表明这是个指针 - 如果函数有
const限定符或引用参数,也要原样写进去,比如void (*cb)(const std::string&) - 使用
typedef或using可读性更高:using cmp_func = bool (*)(int, int);
怎么把函数名赋给函数指针
函数名本身会自动退化为函数指针,不需要加取地址符 &(加了也不报错,但冗余)。但注意:只能赋值「非重载、非模板、非成员」的普通函数。
- 正确:
int add(int a, int b) { return a + b; } cmp_func p = add; - 错误:
p = std::max;(模板函数不能直接取地址) - 错误:
p = obj.method;(非静态成员函数有隐式this参数,类型不匹配) - 若真要存成员函数,得用
std::function或带对象指针的绑定方式
调用函数指针时常见崩溃原因
崩溃往往不是语法问题,而是调用时指针为空或类型不匹配。C++ 不检查函数指针的实际签名,一旦传错参数个数或类型,行为未定义。
- 务必初始化指针:
int (*fp)(int) = nullptr;,调用前判空 - 参数类型严格匹配:
double(*)(float)和double(*)(double)是不同类型,不能混用 - 调用语法有两种等价写法:
fp(42)或(*fp)(42),前者更常用,但别误写成fp[0](42)这类数组访问 - 若函数有可变参数(如
printf风格),函数指针无法安全表达,应避免
用 std::function 替代原生函数指针的时机
原生函数指针轻量、零开销,但太僵硬;std::function 灵活但带小开销(可能堆分配、虚调用)。是否切换,看实际需求。
立即学习“C++免费学习笔记(深入)”;
- 需要存 lambda(尤其捕获变量)、成员函数、bind 表达式时,必须用
std::function - 做回调接口且使用者可能传各种 callable 时,
std::function更友好 - 高频调用(如图形渲染循环里每帧调用)且确定只传普通函数,坚持用原生指针
-
std::function构造失败会抛std::bad_function_call,而原生指针解引用空值直接 UB
函数指针的语法容错率低,一个括号位置错就完全变义;更麻烦的是,类型不匹配在编译期未必报错,运行时才崩。所以定义时多盯两眼括号,赋值时确认函数签名一字不差,比事后调试省太多事。











