函数指针与指针函数:本质区别与高级应用

目录

一、概念本质解析

1. 函数指针(Function Pointer)

2. 指针函数(Pointer Function)

二、函数指针深度剖析

1. 基础用法示例

2. 高级应用:回调函数

3. 函数指针数组

三、指针函数深入探讨

1. 基础实现模式

2. 类成员指针函数(C++)

四、混合使用案例

1. 返回函数指针的函数

2. C++11简化写法

五、工程实践建议

六、典型应用场景

1. 插件系统实现

2. 状态机实现

3. 通用排序算法


一、概念本质解析

1. 函数指针(Function Pointer)

核心概念: 函数指针是一种特殊的指针变量,它不指向数据,而是指向函数的入口地址。通过函数指针,我们可以实现运行时动态调用不同的函数,这是实现回调机制、策略模式等高级编程技巧的基础。

内存视角: 当程序编译后,每个函数都会在代码段分配一块内存空间,函数指针存储的就是这块内存的起始地址。调用函数指针时,CPU会跳转到该地址执行指令。

2. 指针函数(Pointer Function)

核心概念: 指针函数本质上是普通函数,只是它的返回值类型是指针类型。这种函数通常用于:

  • 动态内存分配后返回指针
  • 返回静态/全局变量的地址
  • 返回函数内部静态变量的地址

内存风险: 要特别注意不能返回局部变量的地址,因为函数结束后局部变量的栈空间会被回收。

二、函数指针深度剖析

1. 基础用法示例

#include <stdio.h>// 普通函数定义
int square(int x) {return x * x;
}double cube(double x) {return x * x * x;
}int main() {// 声明函数指针(参数和返回值必须匹配)int (*intFunc)(int) = square;double (*doubleFunc)(double) = cube;printf("Square of 5: %d\n", intFunc(5));printf("Cube of 3.0: %.2f\n", doubleFunc(3.0));// 函数指针重新赋值intFunc = square; // 可以重复指向相同函数printf("Square of 6: %d\n", intFunc(6));return 0;
}

2. 高级应用:回调函数

#include <stdio.h>// 回调函数类型定义
typedef void (*Callback)(int);// 执行某些操作后调用回调
void processData(int data, Callback cb) {printf("Processing data: %d\n", data);// 处理完成后调用回调cb(data * 2);
}// 实际回调函数
void afterProcess(int result) {printf("Process result: %d\n", result);
}int main() {processData(100, afterProcess);// 匿名回调(C99复合字面量)processData(200, (Callback){ [](int x) { printf("Anonymous callback: %d\n", x); } });return 0;
}

3. 函数指针数组

#include <iostream>
#include <vector>void english() { std::cout << "Hello!\n"; }
void french() { std::cout << "Bonjour!\n"; }
void spanish() { std::cout << "Hola!\n"; }int main() {// 初始化函数指针数组void (*greetings[])() = {english, french, spanish};// 遍历调用for (auto func : greetings) {func();}// 结合枚举使用更安全enum Language { EN, FR, ES };void (*langFuncs[])(void) = {[EN] = english,[FR] = french, [ES] = spanish};langFuncs[FR](); // 调用法语问候return 0;
}

三、指针函数深入探讨

1. 基础实现模式

#include <stdlib.h>// 返回动态分配的内存指针
int* createIntArray(int size) {int* arr = (int*)malloc(size * sizeof(int));for (int i = 0; i < size; i++) {arr[i] = i * 10;}return arr;
}// 返回静态变量指针(安全)
const char* getSystemVersion() {static const char* version = "1.2.3";return version;
}int main() {int* myArr = createIntArray(5);// 使用数组...free(myArr); // 必须手动释放const char* ver = getSystemVersion();printf("System version: %s\n", ver);return 0;
}

2. 类成员指针函数(C++)

#include <iostream>
#include <string>class Student {
public:// 指针函数返回动态创建的字符串static char* createName(const std::string& name) {char* buf = new char[name.length() + 1];strcpy(buf, name.c_str());return buf;}// 返回对象自身指针(链式调用)Student* setAge(int age) {this->age = age;return this;}private:int age;
};int main() {char* name = Student::createName("Alice");std::cout << "Name: " << name << std::endl;delete[] name;Student s;s.setAge(20)->setAge(21); // 链式调用return 0;
}

四、混合使用案例

1. 返回函数指针的函数

#include <stdio.h>// 基础运算函数
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 NULL;}
}int main() {int (*operation)(int, int);operation = getOperation('+');printf("10 + 5 = %d\n", operation(10, 5));operation = getOperation('-');printf("10 - 5 = %d\n", operation(10, 5));return 0;
}

2. C++11简化写法

#include <iostream>
#include <functional>auto multiply = [](int a, int b) { return a * b; };
auto divide = [](int a, int b) { return a / b; };// 使用auto返回函数指针
auto getMathFunc(char op) -> int (*)(int, int) {switch(op) {case '*': return multiply;case '/': return divide;default: return nullptr;}
}int main() {using MathFunc = int (*)(int, int);MathFunc func = getMathFunc('*');if (func) {std::cout << "10 * 5 = " << func(10, 5) << std::endl;}// 使用std::function更灵活std::function<int(int,int)> advancedFunc = multiply;std::cout << "Advanced: " << advancedFunc(10, 5) << std::endl;return 0;
}

五、工程实践建议

  1. 函数指针使用规范

    • 使用typedef定义函数指针类型,提高可读性
    • 始终检查函数指针是否为NULL before调用
    • 在C++中优先考虑使用std::function
  2. 指针函数安全准则

    • 明确文档说明返回指针的生命周期
    • 动态分配的内存要配套提供释放函数
    • 避免返回局部变量的地址
  3. 性能考量

    • 函数指针调用比直接调用稍慢(约1-3个时钟周期)
    • 在性能关键路径避免过度使用
    • 现代CPU的分支预测能部分缓解性能损失

六、典型应用场景

1. 插件系统实现

// 插件接口定义
typedef void (*PluginInit)();
typedef void (*PluginRun)(const char*);
typedef void (*PluginCleanup)();// 加载插件
void* loadPlugin(const char* path) {// 动态加载库文件// 获取函数指针PluginInit init = (PluginInit)dlsym(handle, "init");if (init) init();return handle;
}

2. 状态机实现

// 状态处理函数指针类型
typedef void (*StateHandler)(void* context);// 状态定义
StateHandler states[] = {idleHandler,runningHandler,errorHandler
};// 状态切换
void changeState(int newState) {currentHandler = states[newState];
}

3. 通用排序算法

template<typename T>
void sort(T* array, int size, bool (*compare)(const T&, const T&)) {// 使用compare函数指针进行比较for (int i = 0; i < size-1; i++) {if (compare(array[i], array[i+1])) {// 交换元素}}
}

通过深入理解函数指针和指针函数的本质区别及应用场景,开发者可以写出更灵活、更高效的C/C++代码。在实际工程中,这两种技术经常结合使用,创造出强大的编程模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/87161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python】基于pycharm的海康相机SDK二次开发

海康威视二次开发相机管理 这段代码基于python开发的&#xff0c;用了opencv的一些库函数。实现了一个完整的海康机器人相机管理工具&#xff0c;支持多相机连接、参数配置、图像采集和实时显示功能。目前USB相机测试无误&#xff0c;除了丢一些包。 1. 主要类结构 HKCameraM…

HTTP 协议各个主要版本的功能特点、核心原理、使用场景总结

我们来系统总结一下 HTTP 协议各个主要版本的功能特点、核心原理&#xff08;用图示辅助说明&#xff09;以及典型使用场景。 核心演进目标&#xff1a; 提升性能、安全性、效率和灵活性。 1. HTTP/0.9 (1991) - 远古雏形 功能特点: 极其简单&#xff1a; 只支持 GET 方法。无…

Linux编程:3、进程通信-信号

一、进程通信概述 &#xff08;一&#xff09;进程通信的目的 在企业开发中&#xff0c;一个项目常常需要多个进程共同协作&#xff0c;而这些进程之间需要进行通信&#xff08;交换信息&#xff09;以便协作。本章内容主要围绕信号讲解&#xff0c;其它进程通信的常用方式请…

深度解析Vue.js组件开发与实战案例

一、Vue.js组件化思想 Vue.js的核心思想之一就是组件化开发。组件系统是Vue的一个重要概念,它允许我们使用小型、独立和通常可复用的组件构建大型应用。在Vue中,组件本质上是一个拥有预定义选项的Vue实例。 1.1 为什么需要组件化 代码复用:避免重复造轮子,提高开发效率可…

TensorFlow 2.0 与 Python 3.11 兼容性

TensorFlow 2.0 与 Python 3.11 兼容性 TensorFlow 2.0 官方版本对 Python 3.11 的支持有限&#xff0c;可能出现兼容性问题。建议使用 TensorFlow 2.10 或更高版本&#xff0c;这些版本已适配 Python 3.11。若需强制运行&#xff0c;可通过以下方式解决依赖冲突&#xff1a; …

MyBatisPlus 全面学习路径

MyBatisPlus 全面学习路径 学习目录 第一部分&#xff1a;MyBatisPlus 基础 MyBatisPlus 简介与核心特性快速入门与环境搭建核心功能&#xff1a;BaseMapper 与 CRUD 接口条件构造器&#xff08;Wrapper&#xff09;详解ActiveRecord 模式主键策略与通用枚举 第二部分&…

React16,17,18,19更新对比

文章目录 前言一、16更新二、17更新三、18更新四、19更新总结 前言 总结react 16&#xff0c;17&#xff0c;18&#xff0c;19所更新的内容&#xff0c;并且部分会涉及到原理讲解。 一、16更新 1、在16.8之前更新&#xff0c;还是基于class组件的升级和维护更新。并且更新了一…

【git】有两个远程仓库时的推送、覆盖、合并问题

当你执行 git pull origin develop(或默认的 git pull)时,Git 会把远端 origin/develop 的提交合并到你本地的 develop,如果远端已经丢掉(或从未包含)你之前在私库(priv)里提交过的改动,那这些改动就会被「覆盖」,看起来就像「本地修改没了」。 要解决这个问题,分…

Spring Boot 集成国内AI,包含文心一言、通义千问和讯飞星火平台实战教程

Spring Boot 集成国内AI&#xff0c;包含文心一言、通义千问和讯飞星火平台实战教程 一、项目结构二、添加Maven依赖三、配置API密钥 (application.yml)四、配置类1. AI配置类 (AiProperties.java)2. 启用配置类 (AiConfig.java) 五、服务层实现1. 文心一言服务 (WenxinService…

Elastic Search 学习笔记

1. Elasticsearch 是什么&#xff1f;有哪些应用场景&#xff1f; Elasticsearch 整体原理流程&#xff1f; Elasticsearch 是一个为海量数据提供近实时搜索和分析能力的分布式搜索引擎&#xff0c;广泛应用于全文检索、日志分析和大数据处理场景中。 Elasticsearch 整体原理…

动态规划之斐波那契数(一)

解法一&#xff1a;递归 class Solution { public:int fib(int n) {if(n<2) return n;return fib(n-1)fib(n-2);} }; 解法二&#xff1a;dp class Solution { public:int fib(int N) {if (N < 1) return N;int dp[2];dp[0] 0;dp[1] 1;for (int i 2; i < N; i) {…

如何设置爬虫的访问频率?

设置爬虫的访问频率是爬虫开发中的一个重要环节&#xff0c;尤其是在爬取大型网站&#xff08;如1688&#xff09;时&#xff0c;合理的访问频率可以避免对目标网站造成过大负担&#xff0c;同时也能降低被封禁的风险。以下是一些常见的方法和建议&#xff0c;帮助你合理设置爬…

前端面试六之axios

一、axios简介 Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js 环境。在浏览器端&#xff0c;Axios 的底层实现是基于原生的 XMLHttpRequest&#xff08;XHR&#xff09;。它对 XHR 进行了封装&#xff0c;增加了 Promise 支持、自动转换 JSON 数据…

模板方法模式Template Method Pattern

模式定义 定义一个操作中算法的骨架&#xff0c;而将一些步骤延迟到子类中&#xff0c;模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 类行为型模式 模式结构 AbstractClass&#xff1a;抽象类ConcreteClass&#xff1a;具体子类 只有类之间的继…

【行云流水AI笔记】游戏里面的强化学习使用场景

强化学习在游戏中的应用已从早期的棋类博弈扩展到现代复杂游戏的全流程优化&#xff0c;以下是结合最新技术进展的核心应用场景及典型案例&#xff1a; 一、竞技游戏的策略突破 1. 策略博弈类游戏 代表案例&#xff1a;AlphaGo/AlphaZero&#xff08;围棋&#xff09;、Alph…

使用Python和PyTorch框架,基于RetinaNet模型进行目标检测,包含数据准备、模型训练、评估指标计算和可视化

下面是一个完整的实现方案,使用Python和PyTorch框架,基于RetinaNet模型进行目标检测,包含数据准备、模型训练、评估指标计算和可视化。 import os import numpy as np import matplotlib.pyplot as plt import torch import torchvision from torchvision.models.detection…

springboot服务如何获取pod当前ip方案及示例

在 Kubernetes 集群中&#xff0c;Spring Boot 服务获取 Pod 当前 IP 的方案主要有两种&#xff1a;通过环境变量注入 或 通过 Java 代码动态获取网络接口 IP。以下是两种方案的详细说明及示例&#xff1a; 方案一&#xff1a;通过 Kubernetes Downward API 注入环境变量 原理…

1.MySQL三层结构

1.所谓安装的Mysql数据库&#xff0c;就是在电脑上安装了一个数据库管理系统&#xff08;【DBMS】database manage system&#xff09;&#xff0c;这个管理程序可以管理多个数据库。 2.一个数据库中可以创建多个表&#xff0c;以保存数据&#xff08;信息&#xff09;。【数据…

[深度学习]目标检测基础

目录 一、实验目的 二、实验环境 三、实验内容 3.1 LM_BoundBox 3.1.1 实验代码 3.1.2 实验结果 3.2 LM_Anchor 3.2.1 实验代码 3.2.2 实验结果 3.3 LM_Multiscale-object-detection 3.3.1 实验代码 3.3.2 实验结果 四、实验小结 一、实验目的 了解python语…

ALOHA机器人平台:低成本、高精度双臂操作及其进展深度解析

原创1从感知决策到具身智能的技术跃迁与挑战(基座模型与VLA模型)2ALOHA机器人平台&#xff1a;低成本、高精度双臂操作及其进展深度解析3(上)通用智能体与机器人Transformer&#xff1a;Gato和RT-1技术解析及与LLM Transformer的异同4(下)通用智能体与机器人Transformer&#x…