当前位置: 首页 > news >正文

深入解析C++函数指针与指针函数:从原理到实战

🔗 运行环境:C/C++

🚩 撰写作者:左手の明天

🥇 精选专栏:《python》

🔥  推荐专栏:《算法研究》

🔐#### 防伪水印——左手の明天 ####🔐

💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗

💗今天分享【C/C++】——函数指针与指针函数💗

📆  最近更新:2025 年 02 月 22 日,左手の明天的第 354 篇原创博客

📚 更新于专栏:C/C++入门与进阶

🔐#### 防伪水印——左手の明天 ####🔐


一、概念区分

1. 指针函数(Pointer Function)

  • 定义:返回指针类型的函数

  • 本质:普通函数,仅返回值是指针

  • 声明形式返回类型* 函数名(参数列表)

示例如下:

int* getPointer(int value) {
    int* ptr = new int(value);
    return ptr;
}

2. 函数指针(Function Pointer)

  • 定义:指向函数的指针变量

  • 本质:指针变量,存储函数入口地址

  • 声明形式返回类型 (*指针名)(参数列表)

它可以用来调用一个函数或者将一个函数作为参数传递给另一个函数。定义函数指针时,需要指定它所指向的函数的返回类型和参数类型。示例如下:

int add(int a, int b) {
    return a + b;
}

int (*funcPtr)(int, int);

int main() {
    funcPtr = &add;  // 将函数指针指向 add 函数
    std::cout << funcPtr(2, 3) << std::endl;  // 输出 5
    return 0;
}

二、指针函数详解

1. 基础用法

#include <iostream>

// 指针函数:返回int类型指针
int* createArray(int size) {
    int* arr = new int[size];
    for(int i=0; i<size; ++i) {
        arr[i] = i * 10;
    }
    return arr;
}

int main() {
    int* myArray = createArray(5);
    
    for(int i=0; i<5; ++i) {
        std::cout << myArray[i] << " "; // 输出:0 10 20 30 40
    }
    
    delete[] myArray; // 必须手动释放内存
    return 0;
}

2. 注意事项

  • 避免返回局部变量指针

  • 动态内存需要手动释放

  • 推荐使用智能指针(C++11+)

// 危险示例:返回局部变量指针
int* dangerousFunc() {
    int localVar = 42;
    return &localVar; // 警告!返回局部变量地址
}

三、函数指针深度解析

1. 基本声明与使用

#include <iostream>

// 普通函数
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 声明函数指针类型
    int (*operation)(int, int);
    
    operation = &add; // 绑定加法函数
    std::cout << "10 + 5 = " << operation(10, 5) << std::endl;
    
    operation = subtract; // 绑定减法函数(&可选)
    std::cout << "10 - 5 = " << operation(10, 5) << std::endl;
    
    return 0;
}

2. 高级应用:回调函数

#include <vector>

// 回调函数处理数组
void processArray(std::vector<int>& arr, void (*callback)(int&)) {
    for(auto& num : arr) {
        callback(num);
    }
}

// 回调函数示例
void square(int& num) {
    num = num * num;
}

void print(int& num) {
    std::cout << num << " ";
}

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    processArray(numbers, square);  // 平方运算
    processArray(numbers, print);  // 输出:1 4 9 16 25
    
    return 0;
}

3. 使用typedef/using简化

// 使用typedef定义函数指针类型
typedef int (*MathOperation)(int, int);

// C++11 using语法
using MathOp = int (*)(int, int);

int multiply(int a, int b) {
    return a * b;
}

int main() {
    MathOperation op1 = add;
    MathOp op2 = multiply;
    
    std::cout << op1(3,4) << " " << op2(3,4) << std::endl;
    return 0;
}

四、综合对比表

特性指针函数函数指针
本质返回指针的函数指向函数的指针变量
声明关键字*在返回类型后(*指针名)包裹
内存管理需要关注返回值生命周期自动管理函数地址
典型应用场景动态对象创建、工厂模式回调机制、策略模式
复杂度单层指针操作可能涉及多级指针

五、复杂场景应用

1. 返回函数指针的函数

#include <iostream>

int add(int a, int b) { return a+b; }
int sub(int a, int b) { return a-b; }

// 返回函数指针的函数
int (*getOperation(char op))(int, int) {
    switch(op) {
        case '+': return &add;
        case '-': return &sub;
        default: return nullptr;
    }
}

int main() {
    int (*operation)(int, int) = getOperation('+');
    std::cout << "5 + 3 = " << operation(5, 3) << std::endl;
    return 0;
}

2. 函数指针数组

#include <iostream>

void morning() { std::cout << "Good morning!\n"; }
void afternoon() { std::cout << "Good afternoon!\n"; }
void evening() { std::cout << "Good evening!\n"; }

int main() {
    void (*greetings[3])() = {morning, afternoon, evening};
    
    for(int i=0; i<3; ++i) {
        greetings[i]();
    }
    return 0;
}

六、最佳实践与常见陷阱

1. 安全建议

  • 使用nullptr初始化函数指针

  • 调用前检查指针有效性

  • 优先使用C++11的std::function

#include <functional>

int main() {
    // 更安全的现代C++方式
    std::function<int(int,int)> safeOp = add;
    std::cout << safeOp(7, 8) << std::endl;
    return 0;
}

2. 常见错误

// 错误1:参数类型不匹配
double (*wrongOp)(float, float) = add; // 错误!类型不兼容

// 错误2:错误调用方式
int (*op)(int, int) = add;
op = 10; // 错误!不能赋整数值

七、性能与优化

  • 函数指针调用比虚函数快约15%(无分支预测失败)

  • 在紧密循环中建议使用模板替代

  • 现代CPU的间接调用惩罚已显著降低


关键点总结

  1. 指针函数关注返回值类型,函数指针关注参数匹配

  2. 使用typedef/using提升代码可读性

  3. 优先使用智能指针管理动态内存

  4. C++11后推荐std::function+lambda表达式

通过本文的代码实践和原理分析,读者应该能够准确区分和使用这两类重要特性。建议在需要动态行为选择的场景多用函数指针,而在需要生成动态数据的场景合理使用指针函数。


扩展阅读

  1. 《Effective C++》条款41:了解隐式接口和编译期多态

  2. C++17的std::invoke统一调用机制

  3. 函数指针与多态的性能对比分析


 

相关文章:

  • 无法打开包括文件: “crtdbg.h”: No such file or directory
  • 【Blender】二、建模篇--06,曲线建模/父子级和蒙皮修改器
  • 《CentOS 7 镜像源失效终极解决方案(2024年更新)》——生命周期终止后的镜像修复与替代方案
  • Linux编程----filelo(2)
  • 【大模型LLM】DeepSeek LLM Scaling Open-Source Language Models with Longtermism
  • pandas Dataframe介绍以及创建
  • 使用 Python 调用 Ollama API 并调用 deepseek-r1:8b 模型
  • 【量化科普】Liquidity,流动性
  • 鸟语林-论坛系统自动化测试
  • 【网络安全 | 漏洞挖掘】账户接管+PII+原漏洞绕过
  • 【语音科学计算器】当前汇率
  • Python简单使用MinerU
  • 学习Linux准备2
  • 深入理解设计模式之解释器模式
  • 如何设计app测试用例
  • Docker下的Elastic search
  • 使用 LS-DYNA 光滑粒子流体动力学 (SPH) 进行搅拌摩擦焊接
  • 【CXX】3 其它Rust与C++互操作工具详解
  • 网页请求腾讯云环境的云函数
  • 【算法】直接插入排序、折半插入排序、希尔排序
  • 酒店取消订单加价卖何以屡禁不绝?专家建议建立黑名单并在商家页面醒目标注
  • 美联储如期按兵不动,强调“失业率和通胀上升的风险均已上升”(声明全文)
  • 视频丨习近平主席出席俄方在机场举行的迎宾仪式
  • 上海乐高乐园明天正式开售年卡,下月开启试运营
  • 六大车企一季报:比亚迪近92亿净利稳居第一,多家车企营收下滑
  • 上海市政府常务会议部署提升入境旅游公共服务水平,让国际友人“无障碍”畅游上海