RAII机制和智能指针

2024-03-27 21:08
文章标签 指针 智能 机制 raii

本文主要是介绍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结构体一样。最后在函数执行完时包裹对象的内存会被释放。

这篇关于RAII机制和智能指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853390

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

智能交通(二)——Spinger特刊推荐

特刊征稿 01  期刊名称: Autonomous Intelligent Systems  特刊名称: Understanding the Policy Shift  with the Digital Twins in Smart  Transportation and Mobility 截止时间: 开放提交:2024年1月20日 提交截止日

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【Tools】大模型中的自注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一种在Transformer等大模型中经常使用的注意力机制。该机制通过对输入序列中的每个元素计算与其他元素之间的相似性,

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个