函数指针正确声明为 int (func_ptr)(int),括号不可省;赋值需用 &func_name 或隐式转换;调用可用 fp(arg) 或 (fp)(arg);优先用函数指针,泛化需求再选 std::function。

函数指针声明语法容易写反:返回类型在前,不是“函数名在前”
很多人按数组指针类比,误写成 int* func_ptr(int),这其实是声明了一个返回 int* 的函数。正确写法要把指针符号和函数名绑在一起:int (*func_ptr)(int)。括号不能省——* 必须紧贴标识符,否则编译器当成函数声明。
更清晰的写法是用 using 别名:
using FuncPtr = int (*)(int); FuncPtr func_ptr;
这样一眼看出是“指向接收一个 int、返回 int 的函数”的指针。
赋值时不能加括号调用,也不能取地址时漏掉 &
把函数名赋给指针,本质是取函数地址。C++ 允许隐式转换(函数名自动退化为地址),但显式写 &func_name 更安全、语义更明确。常见错误包括:
- 写成
func_ptr = func_name();—— 这是在调用函数,不是取地址 - 写成
func_ptr = &func_name();—— 括号导致先调用再取返回值地址,报错 - 函数重载时隐式转换失败,必须用
&func_name并配合参数类型消除歧义
示例:
int add(int a) { return a + 1; }
int (*fp)(int) = &add; // 推荐:显式取地址
// 或 int (*fp)(int) = add; // 也可,但重载场景下不可靠
调用函数指针时,语法和普通函数一样,但别忘了括号优先级
声明时括号是为了绑定 * 和指针名;调用时,(*fp)(arg) 和 fp(arg) 都合法,后者更常用。但要注意:如果指针本身是表达式结果(比如结构体成员或数组元素),不加括号会出错。
例如:
int (*funcs[2])(int) = {&add, &add};
int r = funcs[0](10); // ✅ 正确
int r = (*funcs[0])(10); // ✅ 也对,但多此一举
int r = *funcs[0](10); // ❌ 编译失败:* 作用于函数调用结果,类型不匹配
所以只要变量名是纯标识符(没带 []、.、-> 等操作),直接 fp(arg) 就行。
函数指针和 std::function 性能与兼容性差异
原生函数指针零开销、无内存分配、可作为模板非类型参数(C++20 起支持),但只能绑定普通函数或静态成员函数。不能绑定 lambda(除非无捕获且强制转型)、不能绑定成员函数(需额外处理 this)。
而 std::function 更通用,但可能触发小对象优化失败时的堆分配,且无法作为模板参数。简单场景优先用函数指针;需要泛化或封装闭包时再切到 std::function。
成员函数指针是另一套语法(Ret (Class::*)(Args)),和普通函数指针不兼容,别混用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











