指針函數、函數指針和指針函數指針的全面總結

C++中指針函數、函數指針和指針函數指針的全面總結

一、核心概念區別

概念本質聲明示例核心特征
指針函數返回指針的函數int* func(int);函數定義,返回值是指針類型
函數指針指向函數的指針int (*ptr)(int);變量,存儲函數地址
指針函數指針指向指針函數的指針int* (*ptr)(int);指針,指向返回指針的函數

二、詳細解析與C++現代替代方案

1. 指針函數(Pointer-Returning Function)

傳統形式

int* createInt(int val) {return new int(val);
}

現代C++替代方案

// 使用智能指針
std::unique_ptr<int> createInt(int val) {return std::make_unique<int>(val);
}// 工廠函數示例
class Widget {};
std::shared_ptr<Widget> createWidget() {return std::make_shared<Widget>();
}

優勢

  • 自動內存管理
  • 異常安全
  • 明確所有權語義

2. 函數指針(Function Pointer)

傳統形式

int add(int a, int b) { return a + b; }
int (*operation)(int, int) = &add;// 使用
int result = operation(3, 4);

現代C++替代方案

// 使用std::function
#include <functional>
std::function<int(int, int)> op = [](int a, int b) { return a + b; };// 使用模板
template<typename F>
void applyOperation(F&& f) {f(3, 4);
}// Lambda表達式
auto multiply = [](int a, int b) { return a * b; };

對比優勢

  • 支持lambda和函數對象
  • 類型更安全
  • 可存儲狀態(捕獲上下文)
  • 更易讀的語法

3. 指針函數指針(Pointer to Pointer-Returning Function)

傳統形式

int* createArray(size_t size) {return new int[size];
}int* (*arrayCreator)(size_t) = &createArray;// 使用
int* arr = arrayCreator(10);

現代C++替代方案

// 使用智能指針和類型別名
using ArrayCreator = std::unique_ptr<int[]>(*)(size_t);
ArrayCreator creator = [](size_t size) { return std::make_unique<int[]>(size); 
};// 或使用std::function
std::function<std::unique_ptr<int[]>(size_t)> creator;

三、現代C++最佳實踐總結

  1. 內存管理

    • 優先使用unique_ptr/shared_ptr
    • 避免裸指針所有權傳遞
  2. 回調機制

    // 傳統(不推薦)
    void registerCallback(void (*callback)(int));// 現代(推薦)
    void registerCallback(std::function<void(int)> callback);
    
  3. 類型簡化技巧

    // 復雜指針類型使用別名
    using ComplexHandler = void (*)(int*, const std::string&);// C++11后更推薦
    using SmartHandler = std::function<void(std::unique_ptr<int>, std::string_view)>;
    
  4. 成員函數處理

    // 傳統成員函數指針
    void (MyClass::*memFunc)(int) = &MyClass::method;// 現代替代方案
    auto lambda = [obj = MyClass()](int x) { obj.method(x); };
    std::bind(&MyClass::method, &obj, std::placeholders::_1);
    

四、何時仍需使用傳統形式

  1. 與C API交互時

    // qsort等C庫函數需要的回調
    extern "C" void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
    
  2. 極度性能敏感場景

    • 函數指針比std::function調用開銷略低
  3. 嵌入式/系統級編程

    • 需要直接操作硬件地址時
  4. 模板元編程

    template<typename T, T (*Allocator)(size_t)>
    class CustomContainer { /*...*/ };
    

五、典型過渡示例

傳統代碼現代C++代碼

// 傳統
float* processData(int (*filter)(float), size_t size) {float* result = new float[size];// 處理...return result;
}// 現代
std::unique_ptr<float[]> processData(std::function<int(float)> filter, size_t size
) {auto result = std::make_unique<float[]>(size);// 處理...return result;
}

六、總結對比表

維度傳統形式現代C++替代方案優勢比較
返回值裸指針智能指針自動內存管理,異常安全
回調函數指針std::function/lambda更靈活,支持狀態捕獲
可讀性復雜聲明類型別名+auto代碼更清晰
類型安全弱類型強類型系統編譯期檢查更嚴格
擴展性僅支持普通函數支持所有可調用對象兼容函數對象、成員函數等

現代C++不是要完全拋棄這些底層概念,而是提供更高層次的抽象,讓開發者可以:

  1. 在需要控制底層時仍能使用傳統方式
  2. 在大多數應用開發中使用更安全、更易用的替代方案
  3. 平滑過渡舊代碼到現代實踐

理解這些底層概念仍然很重要,它們是學習高級抽象的基礎,也是處理特定場景的必要工具。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CherryStudio MCP實戰(一)filesystem篇

隨著DeepSeek的爆火&#xff0c;各行各業都在圍繞著大模型尋找新質量生產力。簡單來說&#xff0c;DeepSeek像是人的大腦&#xff0c;他可以推理&#xff0c;幫你思考一些問題&#xff0c;但是具體要做一些事情的時候&#xff0c;他還需要“手腳”來協同。MCP&#xff08;Model…

TCP基礎篇(一)

文章目錄 1.TCP 是如何保證可靠性的?2. 滑動窗口機制3 超時重傳4.TCP 報文格式5. 什么是 TCP 協議5.1 如何唯一確定一個 TCP 連接 6.TCP 三次握手過程6.1 可以兩次握手嗎? 7.TCP 的四次揮手7.1 為什么客戶端要等待2MSL&#xff1f; 8.linux 中查看 TCP 的連接9.TCP 為什么要有…

【Axure元件分享】時間范圍選擇器

時間范圍選擇器下拉選擇開始時間和結束時間&#xff0c;實現效果如下。 源文件截圖&#xff1a; 元件獲取方式&#xff1a;

大模型學習一:deepseek api 調用實戰以及參數介紹

一、說明 DeepSeek&#xff08;杭州深度求索人工智能基礎技術研究有限公司&#xff09;是一家專注于大語言模型&#xff08;LLM&#xff09;研發的中國創新型科技公司&#xff0c;成立于2023年7月17日&#xff0c;由幻方量化孵化。其核心產品包括開源推理模型DeepSeek-R1、多模…

【Linux網絡與網絡編程】03.UDP Socket編程

一、UDP Socket編程接口 // 創建套接字 int socket(int domain, int type, int protocol); // 參數&#xff1a; // domain&#xff1a;域&#xff08;協議家族&#xff09;&#xff0c;這里使用 AF_INET 表示進行網絡編程 // type&#xff1a;網絡通信傳輸的類型&#xff0…

linux gcc

一、常用編譯選項 ?基本編譯 gcc [input].c -o [output] ?示例&#xff1a; gcc hello.c -o hello # 將 hello.c 編譯為可執行文件 hello ./hello # 運行程序 ?分步編譯 預處理&#xff1a;-E&#xff08;生成 .i 文件&#xff09; gcc -E hello.c -o hello…

若依框架二次開發——RuoYi-AI 集成本地大模型

文章目錄 前提條件1. RuoYi-AI 已成功部署并運行2. Ollama 本地大模型已安裝1. 配置本地大模型2. 切換至本地模型3. 開始對話總結本文將詳細介紹如何在 RuoYi-AI 中集成本地 Ollama 大模型,使系統能夠在 離線環境 下提供智能對話能力。 前提條件 在開始集成本地大模型之前,…

Flask學習筆記 - 模板渲染

Flask 模板渲染 模板是包含占位符的 HTML 文件 Flask 使用 Jinja2 模板引擎來處理模板渲染。模板渲染允許你將動態內容插入到 HTML 頁面中&#xff0c;使得應用能夠生成動態的網頁內容。 創建模板&#xff1a;將 HTML 文件放在 templates 文件夾中&#xff0c;使用 Jinja2 占…

解碼 from XXX import * - 導入的真相

文章目錄 前言一、 什么是 from XXX import *?二、基本用法:導入的實際效果三、默認行為:無 __all__ 的情況四、與直接運行 XXX.py 的對比示例模塊使用 from XXX import *直接運行 python example.py關鍵差異五、為什么需要注意 from XXX import *?最佳實踐六、實際應用場景…

JavaScript 中常見的鼠標事件及應用

JavaScript 中常見的鼠標事件及應用 在 JavaScript 中&#xff0c;鼠標事件是用戶與網頁進行交互的重要方式&#xff0c;通過監聽這些事件&#xff0c;開發者可以實現各種交互效果&#xff0c;如點擊、懸停、拖動等。 在 JavaScript 中&#xff0c;鼠標事件類型多樣&#xff0…

Nacos注冊中心AP模式核心源碼分析(單機模式)

文章目錄 概述一、客戶端啟動主線流程源碼分析1.1、客戶端與Spring Boot整合1.2、注冊實例&#xff08;服務注冊&#xff09;1.3、發送心跳1.4、拉取服務端實例列表&#xff08;服務發現&#xff09; 二、服務端接收請求主線流程源碼分析2.1、接收注冊請求2.1.1、初始化注冊表2…

prism WPF 模塊

模塊 DLL ModuleA 和 ModuleB 都要安裝 Prism.Unity 引用方式1 項目引用 直接 在引用中添加項目引用 App.xaml.cs 添加模塊 ConfigureModuleCatalog using ModuleA; using ModuleB; using Prism.Ioc; using Prism.Modularity; using Prism.Unity; using PrismWpfApp.ViewMo…

CSS:換行與不換行

一、CSS 不允許換行 在 CSS 中&#xff0c;有幾種方法可以控制文本不換行&#xff1a; 1. 使用 white-space 屬性 .no-wrap {white-space: nowrap; } white-space: nowrap; 會強制文本在一行顯示&#xff0c;不換行。 2. 使用 overflow 和 text-overflow 通常與 white-sp…

JavaScript BOM、事件循環

目錄 BOM&#xff08;瀏覽器對象模型&#xff09; 一、window 對象 1. 窗口控制 2. 定時器 二、location 對象 三、navigator 對象 四、history 對象 五、screen 對象 六、本地存儲 1. localStorage 2. sessionStorage 七、BOM 應用場景 八、總結 JavaScript 執行…

k8s運維面試總結(持續更新)

一、你使用的promethues監控pod的哪些指標&#xff1f; CPU使用率 內存使用率 網絡吞吐量 磁盤I/O 資源限制和配額&#xff1a;Prometheus可以監控Pod的資源請求和限制&#xff0c;確保它們符合預設的配額&#xff0c;防止資源過度使用。具體指標如container_spec_cpu_quota用于…

ubuntu20.04升級成ubuntu22.04

命令行 sudo do-release-upgrade 我是按提示輸入y確認操作&#xff0c;也可以遇到配置文件沖突時建議選擇N保留當前配置

Cortex-M? 函數調用的入棧與出棧操作

在 ARM Cortex-M 系列單片機中,普通C函數調用的入棧(壓棧)和出棧操作通常由編譯器編譯后生成的代碼管理,而硬件僅負責部分關鍵操作。以下是詳細分析: 1. 函數調用與返回的核心機制 (1) 硬件自動完成的部分 返回地址的保存: 當通過 BL(Branch with Link)或 BLX 指令調用…

DeepSeek能否用于對話系統(Chatbot)?技術解析與應用實例!

引言&#xff1a;Chatbot 的進化與挑戰 你有沒有發現&#xff0c;現在的AI聊天機器人越來越聰明了&#xff1f;無論是客服助手、智能語音設備&#xff0c;還是社交媒體上的自動回復&#xff0c;Chatbot&#xff08;對話系統&#xff09;已經滲透到我們生活的方方面面。但問題是…

多表查詢的多與一

1.查尋表需要的條件 1.1.首先我們要了解查詢表有哪些 1.1.1.多對一 多對一就是一個年表擁有例外一個表的多條數據 一個表對應立一個表的多條數據&#xff0c;另一個表對應這個表的多條數據 這個點被稱為多對一 1.1.2.多對多 多對多簡單來說就是需要一個中間商 中間商就…

配置文件、Spring日志

SpringBoot配置?件 SpringBoot?持并定義了配置?件的格式, 也在另?個層?達到了規范其他框架集成到SpringBoot的 ?的. 很多項?或者框架的配置信息也放在配置?件 中, ?如: 項?的啟動端? 數據庫的連接信息(包含??名和密碼的設置) 第三?系統的調?密鑰等信息 ?…