成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C++ RAII初探+析構函數

開發 前端
AII并不是一個新鮮的特性,而是古早就有的一種范式。上面例子展示了對象創建的時候獲取資源,對象銷毀的時候釋放資源的例子。

前言

早期編寫的C++是有缺陷的,舉些例子。比如裸指針滿天飛,多線程的數據競爭,雙重釋放等等。但如今的C++正在努力改善這些缺陷,RAII范式的編程在C++比重逐步增加。RAII(Resource Acquisition Is Initialization)是C++之父Bjarne Stroustrup在設計C++的時候就引入了。即:資源獲取即初始化。通俗點,在對象創建的時候獲取資源,在對象銷毀的時候釋放資源。確保內存的安全性。指針shared_ptr就是其中的杰作,下面也會講到。

本篇除了RAII之外,還會分析下其析構函數的關聯。代碼部分,經過C++20測試,均可跑通,可直接用。

RAII操作例子

一個非常簡單的RAII操作,我們初始化對象的時候打開了文件資源。然后在離開對象的作用域的時候,會調用析構函數釋放(關閉)文件資源,例子如下:

//filename:RAII.c
//compile:g++ -g -static -o RAII RAII.c


#include <iostream>
#include <memory>


class File {
public:
    File(const std::string& filename) {
        // 在構造函數中打開文件
        std::cout << "Opening file: " << filename << std::endl;
        file_ = fopen(filename.c_str(), "r");
        if (!file_) {
            throw std::runtime_error("Failed to open file");
        }
    }


    ~File() {
        // 在析構函數中關閉文件
        if (file_) {
            std::cout << "Closing file." << std::endl;
            fclose(file_);
        }
    }


private:
    FILE* file_;
};


int main() {
    try {
        // 創建 File 對象,RAII 確保文件在生命周期結束時自動關閉
        File f("example.txt");


        
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }


    
    return 0;
}

File對象的構造函數里面打開文件,上面代碼運行的結果如下:

圖片圖片

在File對象f離開作用域也即是try塊的結尾大括號處,會調用析構函數,關閉文件。

關于這點我們lldb驗證下,且簡略分析下其原理。在~File()析構函數下斷,其堆棧是在RAII.c:36也即是try塊大括號結尾的地方調用了析構函數。

如下:

(lldb) b ~File()
Breakpoint 2: where = RAII`File::~File() + 16 at RAII.c:17:13, address = 0x000000000040582c
(lldb) r&c
Process 4510 resuming
Opening file: example.txt
Process 4510 stopped
* thread #1, name = 'RAII', stop reason = breakpoint 2.1
    frame #0: 0x000000000040582c RAII`File::~File(this=0x00007fffffffe208) at RAII.c:17:13
   14
   15       ~File() {
   16           // 在析構函數中關閉文件
-> 17           if (file_) {
   18               std::cout << "Closing file." << std::endl;
   19               fclose(file_);
   20           }
(lldb) bt
* thread #1, name = 'RAII', stop reason = breakpoint 2.1
  * frame #0: 0x000000000040582c RAII`File::~File(this=0x00007fffffffe208) at RAII.c:17:13
    frame #1: 0x00000000004055ef RAII`main at RAII.c:36:5
    frame #2: 0x00000000004b7ec8 RAII`__libc_start_call_main + 104
    frame #3: 0x00000000004ba090 RAII`__libc_start_main + 624
    frame #4: 0x0000000000405475 RAII`_start + 37

當我們運行到try塊收尾大括號處,看此時程序剛好調用了File::~File

(lldb) n
Opening file: example.txt
Process 4552 stopped
* thread #1, name = 'RAII', stop reason = step over
    frame #0: 0x00000000004055e3 RAII`main at RAII.c:33:5
   30           File f("example.txt");
   31
   32           // 文件操作...
-> 33       } catch (const std::exception& e) {
   34           std::cerr << e.what() << std::endl;
   35       }
   36
(lldb) di -s $pc
RAII`main:
->  0x4055e3 <+110>: lea    rax, [rbp - 0x58]
    0x4055e7 <+114>: mov    rdi, rax
    0x4055ea <+117>: call   0x40581c       ; File::~File at RAII.c:18:5
    0x4055ef <+122>: mov    eax, 0x0
    0x4055f4 <+127>: mov    rdx, qword ptr [rbp - 0x18]
    0x4055f8 <+131>: sub    rdx, qword ptr fs:[0x28]

也即是代碼:

0x4055ea <+117>: call   0x40581c       ; File::~File at RAII.c:18:5

RAII風格指針

現代C++的幾個指針

  • std::unique_ptr:獨占所有權的智能指針。一個 unique_ptr 只能有一個指針指向資源,因此它不支持復制,只支持轉移所有權。
  • std::shared_ptr:共享所有權的智能指針。多個 shared_ptr 可以共享對資源的所有權,只有最后一個指針被銷毀時,資源才會被釋放。
  • std::weak_ptr:一種不影響資源生命周期的智能指針,用來打破循環引用的問題

我們也來觀察下RAII指針自動調用析構函數釋放的例子

//filename:zhizhen.c
//compile:g++ -std=c++20 -g -static -o zhizhen zhizhen.c
#include <iostream>
#include <memory>


class Resource {
public:
    Resource(const std::string& name) : name_(name) {
        std::cout << name_ << " acquired!" << std::endl;
    }


    ~Resource() {
        std::cout << name_ << " released!" << std::endl;
    }


    void use() {
        std::cout << "Using " << name_ << std::endl;
    }


private:
    std::string name_;
};


void demonstrateWeakPtr() {
    // 創建 shared_ptr 管理 Resource 對象
    std::shared_ptr<Resource> sharedResource = std::make_shared<Resource>("Resource1");


    // 創建 weak_ptr 觀察 shared_ptr
    std::weak_ptr<Resource> weakResource = sharedResource;


    // weak_ptr 不增加引用計數,它只是觀察資源
    std::cout << "Weak pointer created, but it does not affect resource's reference count." << std::endl;


    // 使用 weak_ptr 的 lock 方法來獲取 shared_ptr
    if (auto lockedResource = weakResource.lock()) {
        lockedResource->use();  // 使用資源
    } else {
        std::cout << "Failed to lock weak pointer, resource is not available." << std::endl;
    }


    // 當 shared_ptr 離開作用域時,資源會被釋放
}


int main() {
    demonstrateWeakPtr();  // 資源由 shared_ptr 管理,weak_ptr 只是觀察


    return 0;
}

它的結果如下,同樣的析構函數在離開作用域釋放

圖片圖片

結尾

RAII并不是一個新鮮的特性,而是古早就有的一種范式。上面例子展示了對象創建的時候獲取資源,對象銷毀的時候釋放資源的例子。

我們只需要寫好代碼的規范,其它的編譯器都給做了,比如析構函數的調用等。這種操作,有效的防范了部分內存泄露的可能性。

責任編輯:武曉燕 來源: 江湖評談
相關推薦

2010-02-04 16:39:26

C++析構函數

2010-01-18 15:53:27

C++析構函數

2011-07-15 01:29:39

C++析構函數

2010-02-05 13:35:19

C++虛析構函數

2024-12-19 14:42:15

C++內存泄漏內存管理

2009-08-14 17:24:28

C#構造函數和析構函數

2011-06-09 15:04:22

RAII機制

2009-08-19 09:57:01

C++ RAII

2009-09-03 13:14:55

C#構造函數C#析構函數

2021-12-11 19:02:03

函數C++對象

2009-07-30 15:24:13

C#析構函數C#構造函數

2011-06-15 09:47:14

C++

2010-01-20 14:25:56

函數調用

2024-12-11 16:00:00

C++函數編譯器

2025-04-11 07:50:00

虛析構函數C++開發

2010-01-25 10:10:42

C++函數參數

2009-09-02 10:49:46

C#調用析構方法

2010-07-20 09:52:27

Perl構造函數

2010-07-16 17:12:58

Perl析構函數

2023-10-09 09:02:50

.Net析構函數分配
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲图片视频一区 | 国产伦精品一区二区三区照片91 | 国产视频一二三区 | 浮生影院免费观看中文版 | 免费激情网站 | 亚洲一区二区不卡在线观看 | 久久久国产精品 | 久久婷婷香蕉热狠狠综合 | 国产精品视频一区二区三区 | 国产一区精品在线 | 国产一级毛片精品完整视频版 | 午夜日韩视频 | 成人久久18免费 | 91国语清晰打电话对白 | 国产精品电影在线观看 | 久久久国产精品网站 | 欧美日一区二区 | 国产一级毛片精品完整视频版 | 搞av.com | 国产在线第一页 | 操到爽 | 国产区精品 | 一区日韩 | 99国内精品久久久久久久 | 国产在线1 | 不卡av电影在线播放 | 国产精品美女久久久久久久网站 | 91精品久久久久久久久久入口 | 99视频在线看 | 色综久久| 中文字幕在线观看第一页 | 日日夜夜精品视频 | 91国内精品久久 | 日韩一区二区视频 | 日韩精品1区2区3区 成人黄页在线观看 | 国产精品久久国产精品99 gif | 不卡av在线 | 成人av观看 | 成人午夜高清 | 久久伊人亚洲 | 一区二区三区欧美大片 |