智能指針 c++

C++ 智能指針詳解

智能指針是 C++11 引入的內存管理工具,位于 <memory> 頭文件中,用于自動管理動態分配的內存,防止內存泄漏。主要類型如下:


1. std::unique_ptr (獨占所有權)
  • 特點:唯一擁有所指對象,不可復制(可移動)
  • 適用場景:獨占資源所有權
  • 內存開銷:幾乎為零(僅包裝原始指針)
#include <memory>void unique_ptr_example() {// 創建 unique_ptr (C++14 推薦 make_unique)auto ptr = std::make_unique<int>(42);// 訪問對象*ptr = 100;std::cout << *ptr;  // 輸出 100// 移動所有權auto ptr2 = std::move(ptr);  // ptr 變為 nullptr// 自定義刪除器(處理特殊資源)auto file_deleter = [](FILE* f) { if(f) fclose(f); };std::unique_ptr<FILE, decltype(file_deleter)> file_ptr(fopen("test.txt", "r"), file_deleter);// 離開作用域自動釋放內存
}

2. std::shared_ptr (共享所有權)
  • 特點:多個指針共享對象,使用引用計數
  • 適用場景:需要共享所有權的資源
  • 內存開銷:控制塊(引用計數 + 弱計數)
void shared_ptr_example() {// 創建 shared_ptr (推薦 make_shared)auto ptr1 = std::make_shared<std::string>("Hello");// 共享所有權auto ptr2 = ptr1;  // 引用計數 +1// 查看引用計數std::cout << ptr1.use_count();  // 輸出 2// 自定義刪除器auto arr_deleter = [](int* p) { delete[] p; };std::shared_ptr<int> arr_ptr(new int[10], arr_deleter);// 離開作用域時自動減少引用計數// 引用計數為0時釋放內存
}

3. std::weak_ptr (弱引用)
  • 特點:不增加引用計數,解決循環引用問題
  • 適用場景:打破 shared_ptr 循環引用
  • 用法:需轉換為 shared_ptr 訪問對象
struct Node {std::shared_ptr<Node> next;std::weak_ptr<Node> prev;  // 使用 weak_ptr 避免循環引用
};void weak_ptr_example() {auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2;node2->prev = node1;  // 不會增加引用計數// 訪問 weak_ptr 指向的對象if(auto locked = node2->prev.lock()) {// 成功轉換為 shared_ptr} else {// 對象已被釋放}
}

4. 智能指針對比表
特性unique_ptrshared_ptrweak_ptr
所有權獨占共享無(觀察者)
是否影響引用計數
復制語義禁用(僅移動)允許允許
內存開銷幾乎為零控制塊(約16-32字節)控制塊指針
典型應用場景工廠模式返回值共享數據打破循環引用
線程安全對象訪問需同步引用計數原子操作同 shared_ptr

5. 最佳實踐與注意事項
  1. 優先使用 make_unique/make_shared

    // 更安全高效(單次內存分配)
    auto ptr = std::make_shared<MyClass>(arg1, arg2);
    
  2. 避免循環引用

    • 父對象用 shared_ptr 持有子對象
    • 子對象用 weak_ptr 引用父對象
  3. 不要混用原始指針

    // 危險操作!
    MyClass* raw = new MyClass();
    std::shared_ptr<MyClass> p1(raw);
    std::shared_ptr<MyClass> p2(raw);  // 會導致雙重釋放
    
  4. 接口設計原則

    • 函數接收原始指針:不獲取所有權
    • 函數接收 unique_ptr:獲取所有權
    • 函數返回 unique_ptr:轉移所有權
  5. 特殊資源管理

    // 管理數組 (C++17+)
    auto arr = std::make_unique<int[]>(10);// 管理自定義資源
    auto custom_deleter = [](Resource* r) { cleanup(r); };
    std::unique_ptr<Resource, decltype(custom_deleter)> res(new Resource, custom_deleter);
    

6. 性能考慮
  • unique_ptr:幾乎無開銷,等同于原始指針
  • shared_ptr
    • 控制塊分配開銷(使用 make_shared 可優化)
    • 原子操作引用計數(約比非原子操作慢10倍)
  • 高頻訪問場景:考慮 unique_ptr + 移動語義

7. C++17/20 增強
  1. 數組支持

    // C++17 特有
    auto arr = std::make_unique<int[]>(5);
    arr[0] = 10;
    
  2. std::allocate_shared

    // 自定義分配器
    CustomAllocator alloc;
    auto ptr = std::allocate_shared<MyClass>(alloc, args...);
    
  3. std::weak_from_this

    class MyClass : public std::enable_shared_from_this<MyClass> {
    public:std::weak_ptr<MyClass> weak_ref() {return weak_from_this();  // C++17}
    };
    

8. 常見錯誤
// 錯誤1:返回局部對象的智能指針
std::shared_ptr<int> create() {int value = 42;return std::make_shared<int>(value);  // 正確// return &value;  // 災難!
}// 錯誤2:循環引用
struct A {std::shared_ptr<B> b;  // 應使用 weak_ptr
};
struct B {std::shared_ptr<A> a;  // 應使用 weak_ptr
};// 錯誤3:誤用 get() 管理生命周期
void process(int* raw) { /*...*/ }auto ptr = std::make_unique<int>(10);
process(ptr.get());  // 安全
delete ptr.get();    // 災難!

智能指針是現代 C++ 內存管理的核心工具,正確使用可消除 90% 以上的內存管理問題。

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

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

相關文章

Python應用八股文

大家好!在 Python 學習的道路上&#xff0c;掌握一些基礎知識要點至關重要&#xff0c;這些要點常被稱為“Python 八股”。以下是對它們的簡易總結&#xff0c;幫助你快速回顧和鞏固 Python 的核心概念。 一、數據結構 列表&#xff08;List&#xff09;&#xff1a;有序可變序…

【技術深度】領碼SPARK破解微服務數據依賴困局:架構設計與實踐指南

——深度解析分布式數據冗余與異步消息機制&#xff0c;驅動企業數字化轉型加速 ? 核心摘要 本文從技術架構與工程實現的角度&#xff0c;系統講解領碼SPARK融合平臺如何精準解決微服務架構下數據依賴“卡脖子”問題。通過設計高效的數據冗余模型和完善的異步消息更新機制&am…

關于前端的防抖和節流

給我解釋下 前端開發中的防抖和節流 并舉個具體的例子 防抖&#xff08;Debounce&#xff09;與節流&#xff08;Throttle&#xff09;詳解 在前端開發中&#xff0c;防抖&#xff08;Debounce&#xff09; 和 節流&#xff08;Throttle&#xff09; 是兩種優化高頻觸發事件的…

React-router 多類型歷史記錄棧

react-router 為了滿足開發者更多路由歷史存儲場景&#xff0c;提供了以下幾種模式&#xff1a; 瀏覽器原生歷史記錄 瀏覽器 hash 內存型 服務端記錄 以上實現分別對應于一下 API 實現&#xff1a; createBrowserRouter&#xff1a;瀏覽器提供的歷史管理。 createHashRou…

java設計模式[3]之結構型模式

文章目錄 一 代理模式1.1 靜態代理1.1.1 靜態代理的結構1.1.2 靜態代理的特點1.1.3 靜態代理的應用場景1.1.4 靜態代理的案例代碼 1.2 JDK動態代理1.2.1 JDK動態代理概述1.2.2 JDK動態代理案例代碼1.2.3 JDK動態代理的應用場景1.2.4 JDK動態代理的特點1.2.5 與創建型模式的區別…

鴻蒙Harmony測試-wukong穩定性工具(類似Android的Monkey測試)

一、功能介紹 wukong是系統自帶的一種命令行工具&#xff0c;支持Ability的隨機事件注入、控件注入、異常捕獲、報告生成和對Ability數據遍歷截圖等特性。通過模擬用戶行為&#xff0c;對系統或應用進行穩定性壓力測試。wukong分為隨機測試、專項測試和專注測試。 隨機測試是指…

從零學起VIM

前言 筆者早年剛入行的時候就接觸過Vim,當時還是真正的菜鳥&#xff0c;帶我的師父是一個華為骨干員工&#xff0c;猶記得他給我指導如何保存并關閉文本&#xff1a;按Esc&#xff0c;然后輸入:wq。還記得自己打開Vim編輯器&#xff0c;一個字符都敲不進去&#xff0c;然后問旁…

不依賴rerank 模型排序通過使用 PostgreSQL 中的 pgvector 與 tsearch2 函數進行混合搜索提高召回率

前言 在向量搜索中&#xff0c;召回率是一個關鍵指標&#xff0c;它衡量搜索結果的相關性。然而&#xff0c;提高召回率往往會犧牲其他指標&#xff0c;如索引大小或查詢延遲。為了平衡這些權衡&#xff0c;混合搜索技術應運而生。本文將介紹如何在 PostgreSQL 中結合 pgvecto…

Uniapp 跨平臺開發框架全面解析:一次開發,多端運行

在移動互聯網時代&#xff0c;開發者面臨著一個重要挑戰&#xff1a;如何高效地開發出能在多個平臺&#xff08;iOS、Android、Web、小程序等&#xff09;上運行的應用&#xff1f;傳統的原生開發方式需要為每個平臺單獨編寫代碼&#xff0c;導致開發周期長、維護成本高。而 Un…

ios如何把H5網頁變成主屏幕webapp應用

一、將 H5 頁面添加到主屏幕的步驟 打開 Safari 瀏覽器 在 iPhone 上打開 Safari 瀏覽器&#xff0c;訪問目標網頁&#xff08;H5 頁面&#xff09;。 點擊分享按鈕 在 Safari 瀏覽器底部點擊 “分享” 圖標&#xff08;箭頭向上的按鈕&#xff09;。 添加到主屏幕 在分享菜單…

Node.js 項目啟動命令大全 (形象版)

文章目錄 Node.js 項目啟動命令大全 &#x1f31f;?&#xff08;形象版&#xff09;一、&#x1f50d; 如何查看項目啟動命令&#xff08;魔法書目錄&#xff09;package.json scripts 參數詳解開發相關腳本測試相關腳本構建相關腳本代碼質量相關腳本最佳實踐 二、&#x1f68…

愛普特APT32F1104C8T6單片機 高抗干擾+硬件加密雙保障

愛普特APT32F1104C8T6單片機深度解析 1. 產品定位 APT32F1104C8T6 是愛普特半導體&#xff08;APT&#xff09;推出的 32位高性能經濟型單片機&#xff0c;基于 ARM Cortex-M0內核&#xff0c;采用 LQFP48封裝&#xff0c;主打 高性價比、低功耗、強抗干擾&#xff0c;是替代進…

使用uni-app ios 打包流程

配置幾個步驟即可 1、打包ios需要BundleID ID 2、證書私鑰密碼 3、信任文件證書文件 4、私鑰證書 5、打包 6、獲取打包后的ipa文件 7、通過愛思助手安裝到iso手機上 8、完成 1、下載&#xff1a;App Uploader去獲取我們想要的證書私鑰等文件 2、下載完成解壓后的文件如下打…

仿muduo庫實現并發服務器

1.實現目標 仿muduo庫One Thread One Loop式主從Reactor模型實現高并發服務器&#xff1a; 通過實現高并發服務器的組件&#xff0c;可以快速實現一個高并發服務器的搭建&#xff0c;并且&#xff0c;通過組內不同應用層協議的支持&#xff0c;可以快速完成高性能服務器的搭建…

迭代器模式:集合遍歷的統一之道

引言&#xff1a;集合遍歷的演進之路 在軟件開發中&#xff0c;集合遍歷是我們每天都要面對的基礎操作。從最初的數組索引遍歷到現代的流式處理&#xff0c;我們經歷了&#xff1a; #mermaid-svg-KwTr9k8JgbwRTDhU {font-family:"trebuchet ms",verdana,arial,sans-…

Spring Security OAuth2 組件

我們來系統地講解一下 Spring Security OAuth2 這個強大的組件。我會從概念、作用、核心組件&#xff0c;以及實際應用場景來為你剖析。 1. 什么是 Spring Security OAuth2&#xff1f; 簡單來說&#xff0c;Spring Security OAuth2 是 Spring Security 框架的一個模塊&#…

Redis的持久化功能

Redis的持久化功能能夠將內存中的數據保存到磁盤&#xff0c;從而在重啟后恢復數據。下面為你詳細介紹Redis的兩種主要持久化方式及其配置方法。 RDB&#xff08;Redis Database&#xff09;持久化 RDB持久化是通過生成某個時間點的數據集快照來實現的。它具有高性能的特點&a…

Chrome 將成為下一個 IE6

最近在技術圈刷到一個帖子&#xff0c;說&#xff1a;“Chrome 就快變成新的 IE6 了。” 乍一看有點危言聳聽&#xff0c;但你一細品&#xff0c;發現還真挺像回事。 想當年&#xff1a;IE6 是怎么垮的&#xff1f; IE6 當年多風光&#xff1f;全球市場份額一度超過 90%&#…

Redis 配置文件詳解redis.conf 從入門到實戰

一、redis.conf 是什么&#xff1f; Redis 的配置文件&#xff08;默認命名為 redis.conf&#xff0c;Redis 8.0 之后改為 redis-full.conf&#xff09;控制著服務運行的各項參數。該文件采用以下結構&#xff1a; 指令名 參數1 參數2 ... 參數N例如&#xff1a; replicaof …

autoware docker的安裝

前言 官方的安裝說明&#xff1a; 官方的安裝說明 安裝前&#xff0c;請確認安裝的硬件&#xff1a; CPU with 8 cores16GB RAM[Optional] NVIDIA GPU (4GB RAM) 滿足需求 1. 安裝軟件依賴 這一步主要是安裝三個軟件&#xff1a; DockerNVIDIA Container Toolkit (pref…