C++11-獨占指針unique_ptr原理實現

獨占指針(unique_ptr)是C++11標準引入的一種智能指針,用于獨占管理動態分配對象的生命周期。unique_ptr確保對象在同一時間只有一個所有者,防止對象被多個指針共享。下面是unique_ptr的實現原理及其內存管理機制。

unique_ptr 的基本原理

  1. 獨占所有權

    • unique_ptr 獨占對象的所有權,不能被復制,但可以移動。
    • 通過移動語義,可以將所有權從一個 unique_ptr 轉移到另一個。
  2. 自動內存管理

    • unique_ptr 被銷毀時,它所管理的對象也會被銷毀,自動釋放內存。

實現原理

  1. 基本結構

    • unique_ptr 是一個模板類,包含一個原始指針和一個刪除器。
    • 刪除器是一個可調用對象(如函數指針、函數對象或 std::default_delete),用于在 unique_ptr 銷毀時釋放對象。
  2. 構造與析構

    • 構造函數:接受一個原始指針,默認使用 std::default_delete 作為刪除器。
    • 析構函數:調用刪除器釋放對象。
  3. 禁止復制

    • unique_ptr 禁止復制構造和復制賦值操作。
    • 通過刪除復制構造函數和復制賦值操作符來實現。
  4. 移動語義

    • 允許移動構造和移動賦值操作。
    • 通過移動構造和移動賦值操作符將所有權轉移到另一個 unique_ptr

代碼示例

#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass constructed\n"; }~MyClass() { std::cout << "MyClass destroyed\n"; }void sayHello() { std::cout << "Hello\n"; }
};int main() {std::unique_ptr<MyClass> ptr1(new MyClass());ptr1->sayHello();// std::unique_ptr<MyClass> ptr2 = ptr1; // 錯誤:不能復制 unique_ptrstd::unique_ptr<MyClass> ptr2 = std::move(ptr1); // 移動所有權if (!ptr1) {std::cout << "ptr1 is empty\n";}if (ptr2) {ptr2->sayHello();}return 0;
}

輸出結果

MyClass constructed
Hello
ptr1 is empty
Hello
MyClass destroyed

內存管理機制

  1. 獨占所有權

    • unique_ptr 在同一時間只能有一個所有者,禁止復制操作。
    • 通過移動操作將所有權轉移。
  2. 自動釋放內存

    • unique_ptr 超出作用域或被銷毀時,自動調用刪除器釋放對象內存。

總結

  • unique_ptr 提供了一種安全的、自動的內存管理方式,確保對象不會被多個指針共享。
  • 它通過禁止復制和允許移動操作實現獨占所有權。
  • 使用刪除器在 unique_ptr 銷毀時釋放對象內存,防止內存泄漏。

代碼實現

這里是一個簡單的unique_ptr的實現原理代碼示例。這個示例包含了unique_ptr的核心功能,包括獨占所有權、移動語義以及自動內存管理。

#include <iostream>
#include <utility> // for std::movetemplate<typename T>
class UniquePtr {
private:T* ptr; // 原始指針public:// 構造函數explicit UniquePtr(T* p = nullptr) : ptr(p) {}// 禁止復制構造函數UniquePtr(const UniquePtr&) = delete;// 禁止復制賦值操作符UniquePtr& operator=(const UniquePtr&) = delete;// 移動構造函數UniquePtr(UniquePtr&& other) noexcept : ptr(other.ptr) {other.ptr = nullptr; // 將源指針置為空}// 移動賦值操作符UniquePtr& operator=(UniquePtr&& other) noexcept {if (this != &other) {delete ptr; // 釋放當前持有的資源ptr = other.ptr; // 轉移所有權other.ptr = nullptr; // 將源指針置為空}return *this;}// 析構函數~UniquePtr() {delete ptr; // 釋放資源}// 重載 * 操作符T& operator*() const {return *ptr;}// 重載 -> 操作符T* operator->() const {return ptr;}// 獲取原始指針T* get() const {return ptr;}// 釋放所有權并返回原始指針T* release() {T* temp = ptr;ptr = nullptr;return temp;}// 重新設置指針void reset(T* p = nullptr) {if (ptr != p) {delete ptr; // 釋放當前持有的資源ptr = p; // 設置新的指針}}
};class MyClass {
public:MyClass() { std::cout << "MyClass constructed\n"; }~MyClass() { std::cout << "MyClass destroyed\n"; }void sayHello() { std::cout << "Hello\n"; }
};int main() {UniquePtr<MyClass> ptr1(new MyClass());ptr1->sayHello();// UniquePtr<MyClass> ptr2 = ptr1; // 錯誤:不能復制 unique_ptrUniquePtr<MyClass> ptr2 = std::move(ptr1); // 移動所有權if (!ptr1.get()) {std::cout << "ptr1 is empty\n";}if (ptr2.get()) {ptr2->sayHello();}return 0;
}

代碼說明

  1. 構造函數

    • UniquePtr(T* p = nullptr) : ptr(p) {}:構造函數初始化原始指針。
  2. 禁止復制

    • UniquePtr(const UniquePtr&) = delete;:禁止復制構造函數。
    • UniquePtr& operator=(const UniquePtr&) = delete;:禁止復制賦值操作符。
  3. 移動語義

    • UniquePtr(UniquePtr&& other) noexcept:移動構造函數,從其他UniquePtr轉移所有權,并將源指針置空。
    • UniquePtr& operator=(UniquePtr&& other) noexcept:移動賦值操作符,從其他UniquePtr轉移所有權,并將源指針置空。
  4. 析構函數

    • ~UniquePtr():析構函數釋放資源。
  5. 智能指針接口

    • T& operator*() const:重載解引用操作符。
    • T* operator->() const:重載箭頭操作符。
    • T* get() const:返回原始指針。
    • T* release():釋放所有權并返回原始指針。
    • void reset(T* p = nullptr):重新設置指針,釋放當前持有的資源。

輸出結果

MyClass constructed
Hello
ptr1 is empty
Hello
MyClass destroyed

總結

  • UniquePtr 確保對象在同一時間只有一個所有者,防止多個指針共享。
  • 通過移動語義,可以將所有權從一個 UniquePtr 轉移到另一個。
  • UniquePtr 自動管理對象生命周期,當智能指針超出作用域時自動釋放資源。

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

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

相關文章

618好物推薦,省心省力省錢包!

一年一度的“618”購物狂歡節又來啦&#xff01;大家都心動了吧&#xff0c;購物車也早就堆滿了心儀的好物。別急&#xff0c;別急&#xff0c;讓我給你們推薦幾款真正值得入手的寶貝&#xff0c;讓你們省心、省力還省錢包&#xff01;不管是給自己添置點新裝備&#xff0c;還是…

Vue實現一個動態添加行的表格?

在Vue中實現一個動態添加行的表格可以通過以下步驟來完成&#xff0c;如下所示。 步驟 1&#xff1a;設置表格的數據模型 在Vue組件中定義表格的數據模型&#xff0c;通常使用一個數組來存儲表格的數據。每一行數據可以是一個對象&#xff0c;對象的屬性對應表格的列。 data(…

MFC 編程:Windows 桌面應用程序開發框架

目錄 一.概述 二.MFC 與 Win32 的關系 三.CObject 類 1.CObject 類的主要功能 2.CObject 類的派生類 3.CObject 類成員函數 4.內存管理 對象的創建 對象的銷毀 引用計數 復制對象 5.序列化 序列化的概念 CObject 類的序列化功能 序列化示例 6.運行時類型信息 …

uniapp App去除iOS底部安全區域白邊

未設置的情況下&#xff0c;iOS底部安全區域白邊 如圖&#xff1a; 去除方法&#xff1a; 在 mainfest.json 中加入一下代碼&#xff1a; "safearea" : {"bottom" : {"offset" : "none"} }, 去除效果展示&#xff1a;

Git使用筆記

Git使用筆記 介紹Git推送指定的提交 介紹 Git推送指定的提交 在Git中&#xff0c;如果只想推送一個特定的提交&#xff08;commit&#xff09;&#xff0c;而不是整個分支&#xff0c;可以使用以下步驟&#xff1a; 首先&#xff0c;找到你想要推送的提交的哈希值。通過運行g…

開放式耳機2024超值推薦!教你如何選擇藍牙耳機!

開放式耳機的便利性讓它在我們的日常生活中變得越來越重要。它讓我們擺脫了傳統耳機的限制&#xff0c;享受到了更多的自由。不過&#xff0c;市面上的開放式耳機種類繁多&#xff0c;挑選一款既實用又實惠的產品確實需要一些小竅門。作為一位對開放式耳機頗有研究的用戶&#…

SOLC install 中的問題

solc.install 總是卡死&#xff0c;他拉取的網站出問題了 直接把所有的包都下載下來 sudo add-apt-repository ppa:ethereum/ethereum sudo apt-get update sudo apt-get install solc pip install py-solc-x 文檔 https://web3py.readthedocs.io/en/stable/web3.contract.h…

[WUSTCTF2020]funnyre

ida打開 mian 函數 不能反匯編&#xff0c;往下翻有一處報紅&#xff0c;一看是花指令&#xff0c;還怪長&#xff0c;報紅的都nop后&#xff0c;全選按P重新生成函數 三百多個變量&#xff0c;也是不太可能一個個去解了&#xff0c;剛好前兩天簡單練了一下 angr &#xff08;…

C++多生產者,多消費者模型

C11實現多生產者&#xff0c;多消費者模型 在C標準庫中實現多生產者多消費者模型&#xff0c;可以使用std::thread、std::queue、互斥鎖(std::mutex)、條件變量(std::condition_variable)等組件。下面是一個簡單的示例&#xff0c;展示如何創建多生產者和多消費者模型&#xf…

3款錄屏錄制軟件,打造專業級視頻內容

隨著技術的不斷發展&#xff0c;人們在日常工作和學習中經常會遇到記錄電腦屏幕的需求&#xff0c;例如錄制游戲過程、制作教程、保存會議記錄等。為了解決這一需求&#xff0c;許多錄屏錄制軟件應運而生。本文將介紹三款常見的錄屏錄制軟件&#xff0c;通過分析它們的特點和使…

一文帶你搞懂DiT(Diffusion Transformer)

節前&#xff0c;我們組織了一場算法崗技術&面試討論會&#xff0c;邀請了一些互聯網大廠朋友、今年參加社招和校招面試的同學。 針對大模型技術趨勢、大模型落地項目經驗分享、新手如何入門算法崗、該如何準備面試攻略、面試常考點等熱門話題進行了深入的討論。 總結鏈接…

ArcGIS中分割與按屬性分割的區別

1、分割ArcGIS批量導出各個市的縣級行政邊界 視頻教學&#xff1a; ArcGIS批量導出各個市的縣級行政邊界002 2、ArcGIS批量導出全國各省的邊界 視頻教學&#xff1a; ArcGIS導出全國各省的邊界003 推薦學習&#xff1a; ArcGIS全系列實戰視頻教程——9個單一課程組合系列直播回…

[書生·浦語大模型實戰營]——第二節:輕松玩轉書生·浦語大模型趣味 Demo

1. 部署InternLM2-Chat-1.8B 模型進行智能對話 1.1配置環境 創建開發機 Intern Studio 官網網址&#xff1a;https://studio.intern-ai.org.cn/ 進入官網后&#xff0c;選擇創建開發機&#xff0c;填寫 開發機名稱 后&#xff0c;點擊 選擇鏡像 使用 Cuda11.7-conda 鏡像&am…

CSS中的Flex布局

目錄 一.什么是Flex布局 二.Flex布局使用 2.1Flex使用語法 2.2基本概念 三.容器的屬性 3.1所有屬性概述 3.2flex-direction 3.3flex-wrap 3.4flex-flow 3.5justify-content 3.6align-items 3.7align-content 四.項目(子元素)的屬性 4.1所有屬性概述 4.2order 4…

遺傳算法(Genetic Algorithm, GA)哪些步驟該丟給GPU

遺傳算法&#xff08;Genetic Algorithm, GA&#xff09;是一種啟發式搜索算法&#xff0c;受到生物進化的啟發。在遺傳算法中&#xff0c;種群中的每個個體代表問題的一個候選解&#xff0c;通過迭代選擇、交叉和變異操作&#xff0c;來模擬自然選擇和遺傳過程&#xff0c;從而…

九、OpenAI之圖片生成(Image generation)

學習用DALL.E的API怎樣生成和操作圖片 1 介紹 圖片API提供3個方法來和圖片進行交互&#xff1a; 從0開始基于文字提示創建圖片(DALL.E 3 and DALL.E2)基于一個新的提示詞&#xff0c;通過讓模型替換已有圖像的某些區域來創建圖像的編輯版本;&#xff08;DALL.E2&#xff09;…

【FPGA】Verilog:解碼器 | 編碼器 | 多路復用器(Mux, Multiplexer)

0x00 什么是解碼器 解碼器是根據輸入信號在多個輸出位中選擇一個輸出位的裝置。例如,當解碼器接收2位二進制值作為輸入時,它可以接收00、01、10、11四種輸入值,并根據每個輸入值在4個輸出位中選擇一個,輸出為1000、0100、0010、0001中的一種。這樣的解碼器被稱為高電平有效…

ICML 2024 Mamba 論文總結

2024ICML&#xff08;International Conference on Machine Learning&#xff0c;國際機器學習會議&#xff09;在2024年7月21日-27日在奧地利維也納舉行 &#x1f31f;【緊跟前沿】“時空探索之旅”與你一起探索時空奧秘&#xff01;&#x1f680; 歡迎大家關注時空探索之旅 …