shared_ptr和 weak_ptr的詳細介紹

關于 shared_ptrweak_ptr 的詳細介紹及使用示例:


1. shared_ptr(共享所有權智能指針)

核心特性
  • 引用計數:記錄當前有多少個 shared_ptr 共享同一個對象。
  • 自動釋放:當引用計數歸零時,自動釋放對象內存。
  • 線程安全:引用計數的增減是原子操作(但對象本身的訪問需自行同步)。
基本用法
#include <memory>
#include <iostream>class MyClass {
public:MyClass() { std::cout << "MyClass 構造\n"; }~MyClass() { std::cout << "MyClass 析構\n"; }void print() { std::cout << "Hello\n"; }
};int main() {// 創建 shared_ptr(推薦使用 make_shared)std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();// 共享所有權(引用計數+1)std::shared_ptr<MyClass> ptr2 = ptr1;// 使用 -> 操作符訪問成員ptr1->print(); // 輸出: Hello// 引用計數查看(調試用)std::cout << "引用計數: " << ptr1.use_count() << std::endl; // 輸出: 2// ptr1 和 ptr2 離開作用域,引用計數歸零,對象自動析構return 0;
}
輸出結果
MyClass 構造
Hello
引用計數: 2
MyClass 析構

2. weak_ptr(弱引用智能指針)

核心特性
  • 不增加引用計數:僅觀察對象,不影響其生命周期。
  • 需轉換為 shared_ptr:通過 lock() 獲取臨時 shared_ptr 來訪問對象。
  • 解決循環引用:打破 shared_ptr 的循環依賴,避免內存泄漏。

3. 循環引用問題與 weak_ptr 解決方案

循環引用示例
#include <memory>
#include <iostream>
class Node {
public:std::shared_ptr<Node> next;Node() { std::cout << "Node 構造\n"; }~Node() { std::cout << "Node 析構\n"; }
};int main() {auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2; // node2 引用計數=2node2->next = node1; // node1 引用計數=2// 退出作用域后,node1/node2 引用計數=1,無法釋放!return 0;
}
輸出結果(內存泄漏)
Node 構造
Node 構造
使用 weak_ptr 解決循環引用
#include <memory>
#include <iostream>
class SafeNode {
public:std::weak_ptr<SafeNode> next; // 使用 weak_ptrSafeNode() { std::cout << "SafeNode 構造\n"; }~SafeNode() { std::cout << "SafeNode 析構\n"; }
};int main() {auto node1 = std::make_shared<SafeNode>();auto node2 = std::make_shared<SafeNode>();node1->next = node2;node2->next = node1;// 退出作用域后,引用計數歸零,正確析構return 0;
}
輸出結果
SafeNode 構造
SafeNode 構造
SafeNode 析構
SafeNode 析構

4. weak_ptr 的典型使用場景

(1) 訪問共享對象前檢查存活狀態
#include <memory>
#include <iostream>class MyClass {
public:MyClass() { std::cout << "MyClass 構造\n"; }~MyClass() { std::cout << "MyClass 析構\n"; }void print() { std::cout << "Hello\n"; }
};void checkObject(std::weak_ptr<MyClass> weak) {if (auto shared = weak.lock()) { // 轉換為 shared_ptrshared->print();} else {std::cout << "對象已被釋放\n";}
}int main() {std::weak_ptr<MyClass> weak;{auto shared = std::make_shared<MyClass>();weak = shared;checkObject(weak); // 輸出: Hello}checkObject(weak); // 輸出: 對象已被釋放return 0;
}

輸出結果

MyClass 構造
Hello
MyClass 析構
對象已被釋放
(2) 觀察者模式(緩存)
class DataCache {std::weak_ptr<MyClass> cachedData;
public:void updateCache(std::shared_ptr<MyClass> data) {cachedData = data;}void useCache() {if (auto data = cachedData.lock()) {data->print();} else {std::cout << "緩存無效\n";}}
};

5. shared_ptrweak_ptr 操作總結

操作shared_ptrweak_ptr
所有權擁有對象所有權僅觀察對象
引用計數影響增加不影響
訪問對象直接通過 ->*需調用 lock() 獲取 shared_ptr
檢查有效性if (ptr)if (weak.expired())lock()

6. 最佳實踐

  1. 優先使用 make_shared:更高效(單次內存分配對象+控制塊)。
  2. 避免循環引用:成員指針優先考慮 weak_ptr
  3. 不要用 new 初始化:直接傳遞裸指針可能導致多次釋放。
  4. 謹慎傳遞 shared_ptr:僅在需要共享所有權時傳遞,否則傳遞原始引用或指針。

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

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

相關文章

Spring AI MCP 架構詳解

Spring AI MCP 架構詳解 1.什么是MCP? MCP 是一種開放協議&#xff0c;它對應用程序向大語言模型&#xff08;LLMs&#xff09;提供上下文信息的方式進行了標準化。可以把 MCP 想象成人工智能應用程序的 USB-C 接口。就像 USB-C 為將設備連接到各種外圍設備和配件提供了一種…

騰訊系AI應用,可以生視頻,3D模型...

以下注冊手機后就可以使用了。 騰訊智影 智能抹除-在線去水印去字幕-抹除水印字幕-騰訊智影 混元&#xff08;文字&#xff0c;圖片生成3D&#xff09; 騰訊混元3D 混元視頻&#xff08;文字生成視頻&#xff0c;可惜右下角有文字&#xff09; https://video.hunyuan.tencen…

數據結構(并查集,圖)

并查集 練習版 class UnionFindSet { public:void swap(int* a, int* b){int tmp *a;*a *b;*b tmp;}UnionFindSet(size_t size):_ufs(size,-1){}int UnionFind(int x){}void Union(int x1, int x2){}//長分支改為相同節點int FindRoot(int x){}bool InSet(int x1, int x2)…

數據結構:探秘AVL樹

本節重點 理解AVL樹的概念掌握AVL樹正確的插入方法利用_parent指針正確更新平衡因子掌握并理解四種旋轉方式&#xff1a;左單旋&#xff0c;右單旋&#xff0c;左右雙旋&#xff0c;右左雙旋 一、AVL樹的概念 AVL樹得名于它的發明者G. M. Adelson-Velsky和E. M. Landis&…

電源系統的熱設計與熱管理--以反激式充電器為例

前言 反激電源常用于各種電子設備中&#xff0c;比如充電器、適配器等&#xff0c;它們通過變壓器進行能量轉換。高溫環境可能對電子元件造成影響&#xff0c;特別是像MOSFET、二極管、變壓器這樣的關鍵部件&#xff0c;導致效率變低&#xff0c;甚至可能導致功能失效。還有安…

linux課程學習二——緩存

一.文件io與標準io的一個區別 遇到死循環可以ctrl c結束進程 使用printf輸出&#xff0c;輸出沒有問題 用wirte輸出&#xff0c;參數1&#xff0c;可以理解為上面介紹的linux標準文件描述符的1&#xff08;STDOUT&#xff09;標準輸出&#xff0c;我們加上一個死循環while&…

Kafka中的消息如何分配給不同的消費者?

大家好&#xff0c;我是鋒哥。今天分享關于【Kafka中的消息如何分配給不同的消費者&#xff1f;】面試題。希望對大家有幫助&#xff1b; Kafka中的消息如何分配給不同的消費者&#xff1f; 在 Kafka 中&#xff0c;消息是通過 主題&#xff08;Topic&#xff09; 進行組織的&…

Android的安全問題 - 在 Android 源碼的 system/sepolicy 目錄中,區分 public、private 和 vendor的目的

參考&#xff1a;Google文檔 在 Android 8.0 及更高版本中自定義 SEPolicy 在 Android 源碼的 system/sepolicy 目錄中&#xff0c;區分 public、private 和 vendor 是為了模塊化 SELinux 策略&#xff0c;并明確不同部分的訪問權限和接口邊界。這種設計主要基于以下原因&…

Java NIO之FileChannel 詳解

關鍵點說明 文件打開選項&#xff1a; StandardOpenOption.CREATE - 文件不存在時創建 StandardOpenOption.READ/WRITE - 讀寫權限 StandardOpenOption.APPEND - 追加模式 StandardOpenOption.TRUNCATE_EXISTING - 清空已存在文件 緩沖區操作&#xff1a; ByteBuffer.wrap…

stock-pandas,一個易用的talib的替代開源庫。

原創內容第841篇&#xff0c;專注智能量化投資、個人成長與財富自由。 介紹一個ta-lib的平替——我們來實現一下&#xff0c;最高價突破布林帶上軌&#xff0c;和最低價突破布林帶下軌的可視化效果&#xff1a; cross_up_upper stock[high].copy()# cross_up_upper 最高價突破…

JVM 面經

1、什么是 JVM? JVM 就是 Java 虛擬機&#xff0c;它是 Java 實現跨平臺的基石。程序運行之前&#xff0c;需要先通過編譯器將 Java 源代碼文件編譯成 Java 字節碼文件&#xff1b;程序運行時&#xff0c;JVM 會對字節碼文件進行逐行解釋&#xff0c;翻譯成機器碼指令&#x…

【JavaScript】合體期功法——DOM(一)

目錄 DOMWeb API 基本概念作用和分類 什么是 DOMDOM 樹DOM 對象 獲取 DOM 元素根據 CSS 選擇器來獲取 DOM 元素選擇匹配的第一個元素選擇匹配的多個元素 其他獲取 DOM 元素方法 修改元素的內容對象.innerText 屬性對象.innerHTML 屬性案例&#xff1a;年會抽獎 修改元素屬性修改…

GAMMA數據處理(十)

今天向別人請教了一個問題&#xff0c;剛無意中搜索到了一模一樣的問題 不知道這個怎么解決... ok 解決了 有一個GAMMA的命令可轉換 但是很奇怪 完全對不上 轉換出來的行列號 不知道為啥 再試試 是因為經緯度坐標的小數點位數 de as

Java入門知識總結——章節(二)

ps&#xff1a;本章主要講數組、二維數組、變量 一、數組 數組是一個數據容器&#xff0c;可用來存儲一批同類型的數據 &#x1f511;&#xff1a;注意 類也可以是一個類的數組 public class Main {public static class Student {String name;int age; // 移除 unsignedint…

動態IP:網絡世界的“變色龍”如何改變你的在線體驗?

你知道嗎&#xff1f;有時候我覺得動態IP就像是網絡世界里的“變色龍”。它不像靜態IP那樣一成不變&#xff0c;而是隨時在變化&#xff0c;像是一個永遠在換衣服的演員。你永遠不知道它下一秒會變成什么樣子&#xff0c;但正是這種不確定性&#xff0c;讓它變得特別有趣。想象…

從24GHz到71GHz:Sivers半導體的廣泛頻率范圍5G毫米波產品解析

在5G技術的浪潮中&#xff0c;Sivers半導體推出了創新的毫米波無線產品&#xff0c;為通信行業帶來高效、可靠的解決方案。這些產品支持從24GHz到71GHz的頻率&#xff0c;覆蓋許可與非許可頻段&#xff0c;適應高速、低延遲的通信場景。 5G通信頻段的一點事兒及Sivers毫米波射頻…

aocache:AOCache 新增功能深度解析:從性能監控到靈活配置的全方位升級

最近對aocache 進行了重要升級&#xff0c;最新版本0.6.0增加了幾項新功能&#xff1a;性能分析日志&#xff0c;AOCache性能分析工具&#xff0c;切入點自定義配置&#xff0c;全局配置&#xff0c;本文詳細說明這幾項目新功能的作用和使用方式。 一、性能分析日志 需求背景…

Java EE 進階:MyBatis-plus

MyBatis-plus的介紹 MyBatis-plus是MyBatis的增強工具&#xff0c;在MyBatis的基礎上做出加強&#xff0c;只要MyBatis有的功能MyBatis-plus都有。 MyBatis-plus的上手 添加依賴 在我們創建項目的時候&#xff0c;我們需要添加MyBatis-plus和mysql的依賴 MyBatis-plus的依賴…

GitHub和Gitee上的一些AI項目

以下是GitHub和Gitee上的一些AI項目&#xff1a; GitHub上的AI項目 TensorFlow&#xff1a;一個端到端開源機器學習平臺&#xff0c;包含大量工具和庫&#xff0c;廣泛應用于圖像識別、自然語言處理等領域。PyTorch&#xff1a;由Facebook開發的開源深度學習框架&#xff0c;…

JavaScript網頁設計高級案例:構建交互式圖片畫廊

JavaScript網頁設計高級案例&#xff1a;構建交互式圖片畫廊 在現代Web開發中&#xff0c;交互式元素已成為提升用戶體驗的關鍵因素。本文將通過一個高級案例 - 構建交互式圖片畫廊&#xff0c;展示如何結合HTML和JavaScript創建引人入勝的網頁應用。這個案例不僅涵蓋了基礎的…