IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> RAII机制和智能指针 -> 正文阅读

[C++知识库]RAII机制和智能指针

1 RAII介绍

RAII全称是Resource Acquisition Is Initialization,翻译过来是资源获取即初始化,RAII机制用于管理资源的申请和释放。对于资源,我们通常经历三个过程,申请,使用,释放,这里的资源不仅仅是内存,也可以是文件、socket、锁等等。但是我们往往只关注资源的申请和使用,而忘了释放,这不仅会导致内存泄漏,可能还会导致业务逻辑的错误,RAII就用来解决此类问题。

2 C++中的RAII使用

我们看以下例子。

std::mutex m;
void fn() 
{
    m.lock();                 
    使用资源
    m.unlock();                
}

上面的代码是对互斥变量的使用,我们看到加锁和解锁是成对出现的。如果我们忘了unlock那么别的线程再也无法枷锁成功,而且还会导致一直阻塞。我们看C++怎么解决这个问题。

std::mutex m;
void fn()
{
    std::lock_guard<std::mutex> guard(m); 
    do_something();                            
    // 指向完函数后,guard会被析构,从而mutex也会被释放
}      

我们看到上面的代码中,我们只需要加锁,操作资源,不需要手动解锁。那么RAII是怎么做的呢?我们看看lock_guard的实现。

template <class Mutex> 
class lock_guard {
	private:
	    Mutex& mutex_;
	
	public:
	    lock_guard(Mutex& mutex) : mutex_(mutex) { mutex_.lock(); }
	    ~lock_guard() { mutex_.unlock(); }
		// 禁止复制和赋值
	    lock_guard(lock_guard const&) = delete;
	    lock_guard& operator=(lock_guard const&) = delete;
	};

我们看到实现很简单,在创建一个lock_guard对象的时候,lock_guard会初始化内部字段,并且执行加锁操作。当lock_guard析构的时候,会指向解锁操作,所以借助这个类,我们就不需要关注解锁的操作了,具体的原理是利用了C++对象离开作用域后会自定执行析构函数。

3 RAII实践

3.1 文件管理

理解了使用和原理后,我们也可以利用RAII机制编写自己的类。

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
class FD {
    private:
        int fd;

    public:
        FD(const char *s) { 
            fd = open(s, O_RDONLY); 
            printf("构造函数:打开文件的文件描述符:%d\n", fd);
        }
        ~FD() { 
            int ret = close(fd); 
            printf("析构函数:关闭文件执行结果:%d\n", ret);
        }
        // 重载*运算符
        int operator *() {
            return fd;
        }
        FD(FD const&) = delete;
        FD& operator=(FD const&) = delete;
};

int main()
{
   const char* filePath = "/dev/null";
   FD fd(filePath);
   // 操作资源
   printf("文件描述符:%d\n", *fd);
   return 0;
   // 离开作用域,自动析构,关闭fd
}

我们封装了一个文件管理类,这样我们就可以只关注打开资源,操作资源而不需要手动关闭资源了。

3.2 智能指针

我们再看一下RAII的使用场景,就是智能指针的实现。

#include<iostream>
#include<stdio.h>
using namespace std;

template<class T>
class SmartPoint
{
    T* point;
public:
	SmartPoint(T *ptr = nullptr) :point(ptr) {}

	~SmartPoint() {
		if (point) {
			// 会调用point指向对象的的析构函数
			delete point;
		}
	}
	// 使用智能指针就像使用内部包裹的的对象一样
	T& operator*() { 
		return *point; 
	}

	T* operator->() { 
		return point; 
	}
};

class Demo {
    public:
        Demo() {
            printf("执行构造函数\n");
        }
        ~Demo() {
            printf("执行析构函数\n");
        }
        void show() {
			printf("hello\n");
		}
};

int main() {
    SmartPoint<Demo> smartPoint(new Demo());
    smartPoint->show();
    Demo &demo = *smartPoint;
	demo.show();
}

执行上面代码输出

执行构造函数
hello
hello
执行析构函数

我们看到SmartPoint的实现中,在初始化SmartPoint的时候会传入被管理的对象,并通过重载*和->运算符实现对包裹对象的使用,最后在SmartPoint被析构的时候,也会把包裹对象的内存给析构掉。

4 RAII在Rust的应用

RAII机制和智能指针不仅在C++中使用,在新语言Rust中,同样用到了该技术。

struct Demo(u32);
// 实现Drop trait跟踪Demo的行为
impl Drop for Demo {
    fn drop(&mut self) {
        println!("执行析构");
    }
}
fn main() {
    // 分配堆内存
    let demo_box = Box::new(Demo(1));
    // 操作资源
    println!("{}", demo_box.0);
    // 自动析构
}

执行上面代码输出

1
执行析构

Box就是Rust中的智能指针,使用的方式和C++中类似,初始化Box时传入一个对象,然后交给Box管理,使用demo_box就像是要Demo结构体一样。最后在函数执行完时包裹对象的内存会被释放。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:27:16  更:2021-07-29 11:28:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 1:59:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码