函数指针声明为“返回类型 (指针名)(参数列表)”,括号不可省略且必须紧邻指针名;赋值时函数名自动退化为指针,调用时直接用()无需解引用。

函数指针的声明语法怎么写
函数指针不是「先写函数再加*」,而是把函数名替换成*ptr_name,并保持参数列表和返回类型不变。容易错在括号位置——*必须和指针名紧挨着,且整个指针类型要用括号包住,否则会被解析成函数声明。
比如声明一个指向「返回int、接受两个int参数」的函数的指针:
int (*func_ptr)(int, int);
对比错误写法:int *func_ptr(int, int)——这其实是声明了一个返回int*的函数。
- 返回类型写在最前(如
void、double) -
(*ptr)中间不能有空格,括号不可省略 - 参数列表照抄函数定义里的括号内容,可带参数名也可不带
- 若函数有
const、noexcept、引用参数等修饰,都得一并写上
怎么把函数名赋给函数指针
函数名在大多数上下文中会自动退化为函数指针,所以直接赋值即可,不需要加&(虽然加了也不报错,但多余)。
立即学习“C++免费学习笔记(深入)”;
例如:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
int add(int a, int b) { return a + b; }<br>int (*f)(int, int) = add; // ✅ 正确<br>// int (*f)(int, int) = &add; // ⚠️ 可以,但没必要
- 函数必须已定义或至少已声明,否则编译报错
use of undeclared identifier - 签名必须完全匹配:参数类型、数量、
const性、调用约定(如__cdecl)都不能差 - 类成员函数不能直接赋给普通函数指针,需要
std::function或成员指针语法
调用函数指针时要注意什么
调用方式和普通函数一样,用(),不用解引用操作符*——这是很多人初学时的直觉误区。
下面两种写法等价:
f(3, 4); // ✅ 推荐,简洁清晰<br>(*f)(3, 4); // ✅ 合法,但多此一举
- 如果
f是nullptr就调用,会触发未定义行为(通常是段错误) - 调试时可在调用前加判断:
if (f) result = f(1, 2); - 函数指针本身大小和普通指针一致(通常 8 字节),但不能用
sizeof查它指向的函数大小
用using或typedef简化函数指针类型
原始语法太绕,尤其带const或复杂参数时。C++11 起推荐用using别名,比typedef更直观。
例如:
using CompareFunc = bool (*)(const std::string&, const std::string&);<br>CompareFunc cmp = [](const std::string& a, const std::string& b) { return a < b; }; // lambda 也可赋值(隐式转换)
-
typedef写法:typedef bool (*CompareFunc)(const std::string&, const std::string&); - 别名只简化类型名,不改变语义;仍需确保实际函数签名完全匹配
- 现代 C++ 更倾向用
std::function替代裸函数指针,尤其要支持 lambda、绑定、成员函数时
函数指针本身不保存状态,也不管理生命周期——传进去的函数地址一旦失效(比如局部函数结束),指针就变成悬空的,这点比std::function更难察觉。

















