C++ RAII

RAII定義

RAII(Resource Acquisition Is Initialization)是C++編程中的一種重要的資源管理技術。它的核心思想是:資源的獲取應該在對象的構造階段進行,而資源的釋放則應該在對象的析構階段進行。通過利用C++對象的生命周期和析構函數,在對象生命周期結束時自動釋放資源,從而避免資源泄漏和內存泄漏的發生。
具體來說,RAII 的實現方式是將資源的管理封裝到類中,利用類的構造函數來獲取資源,利用析構函數來釋放資源。這樣,當對象被創建時,資源被獲取;當對象被銷毀時,資源會自動釋放,即使因為異常或者其他原因導致函數提前返回,也能夠保證資源被正確釋放,從而確保資源的正確管理。


示例

文件打開

下面是一個簡單的示例,演示了如何使用 RAII 來管理文件資源:

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>class FileResource {
private:std::ofstream file; // 文件資源std::string filename; // 文件名public:FileResource(const std::string& filename) : filename(filename) {file.open(filename); // 在構造函數中打開文件if (!file.is_open()) {throw std::runtime_error("Failed to open file: " + filename);}std::cout << "File " << filename << " opened successfully." << std::endl;}~FileResource() {if (file.is_open()) {file.close(); // 在析構函數中關閉文件std::cout << "File " << filename << " closed." << std::endl;}}// 寫入數據到文件void writeData(const std::string& data) {if (!file.is_open()) {throw std::runtime_error("File is not open.");}file << data;}
};int main() {try {FileResource file("example.txt"); // RAII:文件資源在構造函數中獲取,在析構函數中釋放// 在文件中寫入數據file.writeData("Hello, RAII!");} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

在這個示例中,FileResource類封裝了文件資源,它的構造函數負責打開文件,而析構函數負責關閉文件。當FileResource對象在main函數中創建時,文件被打開,當對象生命周期結束時,文件會自動關閉,即使在函數中拋出異常,文件也能夠得到正確的關閉。
這個示例展示了 RAII 的核心思想:利用對象生命周期和析構函數來確保資源的正確獲取和釋放,從而提高代碼的健壯性和可維護性。

鎖和內存分配的使用

示例

#include <iostream>
#include <memory>
#include <mutex>// RAII for dynamic memory allocation
class DynamicMemoryResource {
private:int* data;public:DynamicMemoryResource(int size) : data(new int[size]) {std::cout << "Dynamic memory allocated." << std::endl;}~DynamicMemoryResource() {delete[] data;std::cout << "Dynamic memory deallocated." << std::endl;}// Other methods to interact with the allocated memory// ...int getValue(int index) const {return data[index];}void setValue(int index, int value) {data[index] = value;}
};// RAII for locking
class LockResource {
private:std::mutex& mtx;public:LockResource(std::mutex& mutex) : mtx(mutex) {mtx.lock();std::cout << "Mutex locked." << std::endl;}~LockResource() {mtx.unlock();std::cout << "Mutex unlocked." << std::endl;}// Other methods to perform operations while holding the lock// ...
};int main() {try {// RAII for dynamic memory allocationDynamicMemoryResource dynamicMemory(10);// RAII for lockingstd::mutex myMutex;{LockResource lock(myMutex);  // RAII for locking// Perform operations while holding the lockdynamicMemory.setValue(0, 42);std::cout << "Value at index 0: " << dynamicMemory.getValue(0) << std::endl;}// The lock is automatically released when the LockResource object goes out of scope// Other operations after releasing the lock// ...} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

RAII 在c++ 標準庫中的應用

在C++標準庫中,RAII(資源獲取即初始化)的理念廣泛應用于各種類和功能。以下是一些C++標準庫中常見的RAII應用:

智能指針

std::unique_ptr 和 std::shared_ptr 提供了自動管理動態分配的內存資源的機制。當指針超出作用域時,它們會自動釋放所持有的內存。

#include <memory>
#include <iostream>int main() {std::unique_ptr<int> ptr(new int(42));std::cout << *ptr << std::endl; // 輸出: 42// 在ptr超出作用域后,自動釋放所持有的內存
}


文件流

std::ifstream 和 std::ofstream 等文件流類利用RAII來確保在文件操作完成后自動關閉文件。文件資源在對象生命周期結束時被釋放。

#include <fstream>int main() {std::ofstream file("example.txt");file << "Hello, RAII!";// file對象超出作用域后,文件自動關閉
}


標準容器

標準容器如 std::vector、std::string 在內部使用RAII原則來管理其元素的內存。當容器對象銷毀時,相關的資源被自動釋放。

#include <vector>int main() {std::vector<int> vec{1, 2, 3, 4, 5};// vec對象超出作用域后,自動釋放內存
}


互斥鎖

std::mutex 和 std::lock_guard 用于實現線程同步,其中 std::lock_guard 利用RAII確保在作用域結束時釋放鎖資源,避免忘記手動釋放鎖。

#include <mutex>
#include <thread>
#include <iostream>std::mutex mtx;void task() {std::lock_guard<std::mutex> lock(mtx);std::cout << "Critical section" << std::endl;// lock對象超出作用域后,自動釋放鎖資源
}int main() {std::thread t1(task);std::thread t2(task);t1.join();t2.join();
}


文件系統庫

C++17 引入的 <filesystem> 庫中的路徑、文件迭代器等對象也遵循RAII原則,確保在作用域結束時資源被正確釋放。

#include <filesystem>
#include <iostream>namespace fs = std::filesystem;int main() {fs::path filePath = "example.txt";// filePath對象超出作用域后,自動釋放資源
}


計時器

std::chrono 庫中的定時器類,如 std::chrono::steady_clock::time_point,在其生命周期結束時會自動釋放相關資源。

#include <chrono>
#include <iostream>int main() {auto start = std::chrono::steady_clock::now();// 在start超出作用域后,自動釋放資源
}

異常安全性

C++標準庫中的很多異常安全性保障都使用了RAII,例如 std::lock_guard 在異常發生時仍能正確釋放鎖資源,確保不會發生資源泄漏。

#include <iostream>
#include <stdexcept>int main() {try {// 執行一些可能拋出異常的操作throw std::runtime_error("An error occurred");} catch(const std::exception& e) {std::cerr << "Exception caught: " << e.what() << std::endl;// 在catch塊中,資源會被正確釋放}
}


線程

std::thread 類在其析構函數中處理了線程資源的清理,確保在線程對象銷毀時相關資源被釋放。

#include <thread>
#include <iostream>void task() {std::cout << "Thread task" << std::endl;
}int main() {std::thread t(task);t.join();// t對象超出作用域后,線程資源會被正確釋放
}

這些都是C++標準庫中使用RAII的一些常見例子。通過RAII,C++標準庫實現了自動化的資源管理,提高了代碼的可維護性和安全性。

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

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

相關文章

C#之WPF學習之路(2)

目錄 控件的父類 DispatcherObject類 DependencyObject類 DependencyObject 類的關鍵成員和方法 Visual類 Visual 類的主要成員和方法 UIElement類 UIElement 類的主要成員和功能 FrameworkElement類 FrameworkElement 類的主要成員和功能 控件的父類 在 WPF (Windo…

谷粒商城篇章9 ---- P248-P261/P292-P294 ---- 消息隊列【分布式高級篇六】

目錄 1 消息隊列(Message Queue)簡介 1.1 概述 1.2 消息服務中兩個重要概念 1.3 消息隊列主要有兩種形式的目的地 1.4 JMS和AMQP對比 1.5 應用場景 1.6 Spring支持 1.7 SpringBoot自動配置 1.7 市面上的MQ產品 2 RabbitMQ 2.1 RabbitMQ簡介 2.1.1 RabbitMQ簡介 2…

什么是Elasticsearch SQL

什么是Elasticsearch SQL 一. 介紹二. SQL 入門 前言 這是我在這個網站整理的筆記,有錯誤的地方請指出&#xff0c;關注我&#xff0c;接下來還會持續更新。 作者&#xff1a;神的孩子都在歌唱 一. 介紹 Elasticsearch SQL 是一個 X-Pack 組件&#xff0c;允許針對 Elasticsea…

通俗易懂理解G-GhostNet輕量級神經網絡模型

一、參考資料 原始論文&#xff1a;[1] IJCV22 | 已開源 | 華為GhostNet再升級&#xff0c;全系列硬件上最優極簡AI網絡 二、G-GhostNet相關介紹 G-GhostNet 又稱為 GhostNetV1 的升級版&#xff0c;是針對GPU優化的輕量級神經網絡。 1. 摘要 GhostNetV1 作為近年來最流行…

Leetcode 611.有效三角形的個數

題目 給定一個包含非負整數的數組 nums &#xff0c;返回其中可以組成三角形三條邊的三元組個數。 示例 1: 輸入: nums [2,2,3,4] 輸出: 3 解釋:有效的組合是: 2,3,4 (使用第一個 2) 2,3,4 (使用第二個 2) 2,2,3示例 2: 輸入: nums [4,2,3,4] 輸出: 4提示: 1 < nums…

Android的LiveData

LiveData 是一種可觀察的數據存儲器類。與常規的可觀察類不同&#xff0c;LiveData 具有生命周期感知能力&#xff0c;意指它遵循其他應用組件&#xff08;如 activity、fragment 或 service&#xff09;的生命周期。這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態的…

ChatGPT在醫學領域的應用與前景

標題&#xff1a; ChatGPT在醫學領域的應用與前景 正文&#xff1a; 隨著人工智能技術的不斷進步&#xff0c;ChatGPT等語言模型在醫學領域的應用逐漸深入&#xff0c;展現出其巨大的潛力和廣闊的發展前景。作為一個高級的自然語言處理工具&#xff0c;ChatGPT能夠理解和生成…

WPF 開發調試比較:Visual Studio 原生和Snoop調試控制臺

文章目錄 前言運行環境簡單的WPF代碼實現一個簡單的ListBoxVisual Studio自帶代碼調試熱重置功能測試實時可視化樹查找窗口元素顯示屬性 Snoop調試使用Snoop簡單使用調試控制臺元素追蹤結構樹Visual/可視化結構樹Logical/本地代碼可視化樹AutoMation/自動識別結構樹 WPF元素控制…

基于springboot+vue的房屋租賃管理系統(前后端分離)

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

【OpenAI官方課程】第四課:ChatGPT文本推斷Summarizing

歡迎來到ChatGPT 開發人員提示工程課程&#xff08;ChatGPT Prompt Engineering for Developers&#xff09;&#xff01;本課程將教您如何通過OpenAI API有效地利用大型語言模型&#xff08;LLM&#xff09;來創建強大的應用程序。 本課程由OpenAI 的Isa Fulford和 DeepLearn…

手拉手Vite+Vue3+TinyVue+Echarts+TailwindCSS

技術棧springboot3hutool-alloshi-coreVue3viteTinyVueEchartsTailwindCSS軟件版本IDEAIntelliJ IDEA 2022.2.1JDK17Spring Boot3.1hutool-all5.8.18oshi-core6.4.1Vue35.0.10vite5.0.10axios1.6.7echarts5.4.3 ECharts是一個使用 JavaScript 實現的開源可視化庫&#xff0c;可…

快速搭建ARM64實驗平臺(QEMU虛擬機+Debian)

文章目錄 前言一、實驗平臺介紹二、安裝步驟2.1 安裝工具2.2 下載倉庫2.3 編譯內核并制作根文件系統2.4 運行剛才編譯好的ARM64版本的Debian系統2.5 在線安裝軟件包2.6 在QEMU虛擬機和主機之間共享文件 三、單步調試ARM64 Linux內核參考資料 前言 最近翻閱笨叔的《奔跑吧Linux…

go-zero微服務入門教程

go-zero微服務入門教程 本教程主要模擬實現用戶注冊和用戶信息查詢兩個接口。 準備工作 安裝基礎環境 安裝etcd&#xff0c; mysql&#xff0c;redis&#xff0c;建議采用docker安裝。 MySQL安裝好之后&#xff0c;新建數據庫dsms_admin&#xff0c;并新建表sys_user&#…

【Git】 刪除遠程分支

Git 刪除遠程分支有以下幾種方法 服務端UI工具 Git 的服務端圖形化工具主要是 web 端。常用的有 GitHub、Gitea、Gutlab 等。 這些工具都提供了分支管理&#xff0c;可以直接在各服務端找到相關功能&#xff0c;謹慎刪除。 客戶端UI工具 Git 擁有諸多客戶端 UI 工具&#x…

詳細分析Python中的unittest測試框架

目錄 1. 基本知識2. API2.1 斷言2.2 setUp() 和 tearDown() 3. Demo 1. 基本知識 unittest 是 Python 標準庫中的一個單元測試框架&#xff0c;用于編寫和執行測試用例以驗證代碼的正確性 提供了一種結構化的方法來編寫測試&#xff0c;使得測試代碼更加模塊化和易于維護 以…

【ACW 服務端】頁面操作Java增刪改查代碼生成

版本: 1.2.2-JDK17-SNAPSHOT 項目地址&#xff1a;wu-smart-acw 演示地址&#xff1a;演示地址 admin/admin Java增刪改查代碼生成 找到對應菜單 選擇你需要的數據實例 選擇數據庫 選擇數據庫表 選擇客戶端&#xff08;如果是本地ACW服務代碼啟動默認注冊上的客戶端ID是…

騰訊云主機Ubuntu22.04安裝Odoo17

一、安裝PostgreSQL16 參見之前的文章 Ubuntu22.04安裝PostgreSQL-CSDN博客 二、安裝Odoo17 本方案使用的nightly版的odoo&#xff0c;安裝的都是最新版odoo wget -O - https://nightly.odoo.com/odoo.key | apt-key add - echo "deb http://nightly.odoo.com/17.0/n…

Maven【1】(命令行操作)

文章目錄 一丶創建maven工程二、理解pom.xml三、maven的構建命令1.編譯操作2.清理操作3.測試操作4.打包操作5.安裝操作 一丶創建maven工程 首先創建這樣一個目錄&#xff0c;然后從命令行里進入這個目錄&#xff1a; 然后接下來就在這個命令行里進行操作了。 這個命令是&…

Python學習筆記——PySide6設計GUI應用之UI與邏輯分離

1、打開PySide6的UI設計工具pyside6-designer&#xff0c;設計一個主窗口&#xff0c;保存文件名為testwindow.ui 2、使用PySide6的RCC工具把testwindow.ui文件轉換為testwindow_rc.py文件&#xff0c;此文件中有一個類Ui_MainWindow&#xff08;包含各種控件對象&#xff09;…

設計模式淺析(八) ·外觀模式

設計模式淺析(八) 外觀模式 日常叨逼叨 java設計模式淺析&#xff0c;如果覺得對你有幫助&#xff0c;記得一鍵三連&#xff0c;謝謝各位觀眾老爺&#x1f601;&#x1f601; 外觀模式 概念 外觀模式&#xff08;Facade Pattern&#xff09;是一種設計模式&#xff0c;它為…