RAII 与智能指针

【RAII 思想】RAII 基本概念(一种思想) RAII(Resource Acquisition Is Initialization)是一种C++编程技术,它通过在对象的构造函数中获取资源,在对象的析构函数中释放资源,从而确保资源的正确获取和释放。RAII(Resource Acquisition Is Initialization)是一种C++编程技术,它通过在对象的构造函数中获取资源,在对象的析构函数中释放资源,从而确保资源的正确获取和释放。当使用RAII时,资源的获取和释放被封装在对象的构造函数和析构函数中,从而确保资源的正确获取和释放。 阅读详情

1.什么是 RAII

1.概念
Resource Acquisition Is Initialization 资源获取即初始化。一般分为 3 步,当我们在main函数中声明一个局部对象的时候,会自动调用构造函数进行对象的初始化,当整个main函数执行完成后,自动调用析构函数来销毁对象,整个过程无需人工介入,由操作系统自动完成;

2.如何使用 raii

智能指针(std::shared_ptr和std::unique_ptr)即RAII最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏。

还有就是锁,有可能出现初始化锁但是没有释放锁的情况

2.智能指针

智能指针源码实现

导入头文件

#include <memory>

2.1 内存泄露

一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定)内存块,使用完后必须显式释放的内存。应用程序般使用malloc,、realloc、 new等函数从堆中分配到块内存,

避免内存泄露的几种方式

  • 计数法:使用new或者malloc时,让该数+1,delete或free时,该数-1,程序执行完打印这个计数,如果不为0则表示存在内存泄露
  • 一定要将基类的析构函数声明为虚函数
~A() = default;
  • 对象数组的释放一定要用delete []
  • 有new就有delete,有malloc就有free,保证它们一定成对出现

检测工具

  • Linux下可以使用Valgrind工具

    https://blog.youkuaiyun.com/qq_20553613/article/details/106503929

会显示有几个指针是 free 的有几个指针是 alloc 的,显示是在哪一行出错的,同样 Valgrind 还能检测其他的内存问题:

valgrind --tool=memcheck --leak-check=full ./a

使用空指针

使用野指针:指向了一个根本不存在或者已经被释放的指针

内存空间访问越界

内存空间未释放

内存空间重复释放

内存空间申请和释放不匹配

  • Windows下可以使用CRT库

3.auto_ptr

定义:auto_ptr的实现原理其实就是RAII,在构造的时候获取资源,在析构的时候释放资源,并进行相关指针操作的重载

抛弃原因:因为有拷贝构造和赋值的情况下原有的对象会被释放

https://blog.youkuaiyun.com/Dasis/article/details/121663794

(1)赋值

当我们对智能指针进行赋值时,如 ptest2 = ptest,ptest2会接管ptest原来的内存管理权,ptest会变为空指针,如果ptest2原来不为空,则它会释放原来的资源

(2)数组传递值,本质也是移动拷贝

void foo_ary()
{
    std::vector<std::auto_ptr<int>> Ary;
    std::auto_ptr<int> p(new int(3));
    //push_back时不允许如此构造对象
    Ary.push_back(p);

    printf("%d\r\n", *p);
}

4.shared_ptr

多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。

(1)创建

std::shared_ptr<int> p3(new int(10));
std::shared_ptr<int> p5 = std::make_shared<int>(10);
//调用拷贝构造函数
std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
//调用移动构造函数
std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);

(2) 源码

//
// Created by xuboluo on 2022/9/5.
// shared_prt_demo

#include <iostream>
template <typename T>
class my_shared{
  int count_;
  T* ptr_;
  public:
  // 创建构造函数
  // 1. 默认构造函数
  my_shared():count_(0),ptr_(nullptr){}
  // 2. 传入的是对象
  my_shared(T* ptr):ptr_(ptr),count_(1){}
  // 3.传入的是智能指针
  my_shared(const my_shared<T>& other):count_((other.count_+1)),ptr_(other.ptr_){}

  // 析构函数
  ~my_shared(){
    count_--;
    if(ptr_&&count_==0){
      delete ptr_;
    }
  }
  // operator = 的方法
  my_shared* operator=(const my_shared<T>& other){
    if(this==&other) return this;
    other.count_++;
    // 将 prt2 指向的对象给 ptr1 ,并将自己原先的进行释放
    if(this->ptr_&&0==--this->count_){
      delete ptr_;
    }
    // 释放完之后再向 ptr 赋值
    this->ptr_ = other.ptr_;
    this->count_ = other.count_;
    return this;
  }
  // use_count
  int use_count(){
    return count_;
  }
};
int main(){
  int* p = new int(3);
  my_shared<int> ptr(new int(3)); // 传入一个对象的指针
  my_shared<int> ptr2(ptr); // 传入一个智能指针
  my_shared<int> ptr3 = ptr2;
  std::cout<<ptr3.use_count();
}

(3)Shared_ptr 的循环引用
如果相互引用 shared_ptr 会造成程序死锁,最终谁也不释放资源
Demo

5.weak_ptr

解决 shared_ptr 相互引⽤时,两个指针的引⽤计数永远不会下降为0,从⽽导致死锁问题。⽽ weak_ptr 是对对象的⼀种弱引⽤,可以绑定到 shared_ptr ,但不会增加对象的引⽤计数。

如何判断 weak_ptr 失效:1.expired():检查被引用的对象是否已删除。2.lock()会返回shared指针,判断该指针是否为空。3.use_count()也可以得到shared引用的个数,但速度较慢

(1)创建

std::shared_ptr<int> sp (new int);
std::weak_ptr<int> wp3 (sp);

(2)如何使用

#include <iostream>
#include <memory>
using namespace std;

int main()
{
  std::shared_ptr<int> sp1(new int(10));
  std::shared_ptr<int> sp2(sp1);
  std::weak_ptr<int> wp(sp2);
  //输出和 wp 同指向的 shared_ptr 类型指针的数量
  cout << wp.use_count() << endl; // 2
  //释放 sp2
  sp2.reset();
  cout << wp.use_count() << endl; // 1 
  //借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据
  cout << *(wp.lock()) << endl; // 10
  return 0;
}

6.unique_ptr

是作用域指针,当超出作用域时就会被销毁然后调用 delete。同⼀时间只能有⼀个智能指针可以指向该对象,每个 unique_ptr 指针指向的堆内存空间的引用计数,都只能为 1,一旦该 unique_ptr 指针放弃对所指堆内存空间的所有权,则该空间会被立即释放回收,而且 unique_ptr 的拷贝构造函数和 operator= 都被 delete 了

(1)创建

std::unique_ptr<int> p4(new int);
std::unique_ptr<int> p5(p4);//错误,堆内存不共享
std::unique_ptr<int> p5(std::move(p4));//正确,调用移动构造函数

(2)如何使用

#include <iostream>
#include <memory>
using namespace std;

int main()
{
    std::unique_ptr<int> p5(new int);
    *p5 = 10;
    // p 接收 p5 释放的堆内存
    int * p = p5.release();
    cout << *p << endl; // 10
    //判断 p5 是否为空指针
    if (p5) {
        cout << "p5 is not nullptr" << endl;
    }
    else {
        cout << "p5 is nullptr" << endl; // null 
    }

    std::unique_ptr<int> p6;
    //p6 获取 p 的所有权
    p6.reset(p);
    cout << *p6 << endl; // 10
    return 0;
}
C++的RAII思想以及在智能指针上的应用 C++中资源获取即初始化(RAII)的介绍,以及在智能指针上的实现 阅读详情

相关推荐

C++:什么是RAII? | 智能指针的初步讲解 | 智能指针是为了避免什么问题?| 被遗弃的auto_ptr

文章目录一、什么是RAIIRAlI的原理二、智能指针的引入1.为什么要使用智能指针三、被弃用的auto_ptr模拟实现auto_ptr(*)和(->)重载 一、什么是RAII RAll (Resource Acquisition ls Initialization)是由c++之父Bjarne Stroustrup提出的,中文翻译为资源获取即初始化,使用局部对象来管理资源的技术称为资源获取即初始化;这里的资源主要是指操作系统中有限的东西如内存(heap)、网络套接字,互斥量,文件句柄等等,局部对象是指存

Sauron7i的博客 1812

C++:什么是RAII?|智能指针

这里的资源主要是指操作系统中有限的东西如内存(heap)、网络套接字,互斥量,文件句柄等等,局部对象是指存储在栈的对象,它的生命周期是由操作系统来管理的,无需人工介入。从该示例可以看出,当我们在fun函数中声明一个局部对象的时候,会自动调用构造函数进行对象的初始化,当整个fun函数执行完成之后,自动调用析构函数来销毁对象,整个过程无需人工介入,由操作系统自动完成,于是自然联想到,当我们在使用资源的时候,在构造函数中进行初始化,在析构函数中进行销毁。智能指针虽然很智能,但容易被误用,智能也是有代价的。

m0_57719144的博客 6459

Xilinx UltraScale+ FPGA实战:手把手教你实现USB3.0设备开发(附原理图+代码)

本文详细介绍了如何使用Xilinx UltraScale+ FPGA开发USB3.0设备,涵盖硬件设计、Vivado工程配置、Petalinux系统定制及功能测试全流程。通过实战案例和优化技巧,帮助开发者快速掌握高速数据传输实现方法,提升嵌入式系统开发效率。

weixin_29159995的博客 209

C++: RAII是什么——使用对象来管理资源

在本文中,我们介绍了C++中的RAII技术,它是一种管理资源的方法,可以帮助我们避免内存泄漏和资源泄漏等问题。在函数中由栈管理的临时对象,在函数结束时会自动析构,从而自动释放资源,因此,我们可以。本文较为详细介绍了RAII的原理、使用方法和优点,并且通过实例讲解了RAII在C++ STL中的应用,如智能指针和互斥锁等,在最后进行了编程实践。

wsqiangz的博客 5310

SQLite → PostgreSQL 迁移脚本与踩坑清单

本文提供了SQLite迁移到PostgreSQL的两种可靠路径:首选使用pgloader工具自动转换schema和数据,支持类型映射和并行复制;备选方案通过sqlite3导出CSV再用PostgreSQL的COPY命令导入,适合需要自定义清洗的场景。重点介绍了数据类型映射规则、迁移步骤、校验方法和常见问题,包括自增主键、布尔值、时间类型等关键差异处理。迁移后需进行行数核对、哈希抽样等校验,并给出了性能优化建议。最后强调迁移不仅是数据转移,更需要同步升级数据模型和索引策略,根据业务场景选择合适的数据库方案。

aifs2025的博客 1885

similarity network fusion for aggregating data types on a genomic scale

基因组规模上的聚合数据类型的相似性网络融合 摘要:         近期的技术已经使收集不同类型的全基因组数据十分划算,结合这些数据去创建一个给定的疾病或生物过程的一个全面视图的计算方法是有必要的。相似网络融合(SNF:similarity network fusion)通过创建每一个可利用的数据类型的样本(如,患者)的网络可以解决这个问题。例如,创建一个给定一群患者疾病的全面视图,SNF计算

augustar学习笔记 7869

RAII与智能指针

本文主要介绍C++中的RAII理念以及智能指针的使用,并举出了相应的例子进行举例说明。

weixin_43308899的博客 1245

PSM倾向匹配详细步骤和程序

目录1.安装psmatch2统计包。2.数据准备3.数据分析及命令解读4.结果解读4.1模型拟合结果,此处无太多实际意义。4.2试验组可匹配的观测概览,按照命令中设定的匹配规则,试验组有8例患者未能匹配到合适对照。4.3结果解读的重点应该是对stata新生成的中间变量的解读。4.4均衡性检验结果4.5匹配结果的图示化5.Stata命令汇总最后留下两个问题给大家思考:题目 试验设计中,匹配的目的在于确保干预效应估计是建立在可比个体之间的不同结果的基础上。最简单的匹配方式是将干预组和对照组中协变量值相同的两个个

平平淡淡,戒急用忍,一生学闭嘴。 5万+

【C++】智能指针(RAII)详解

我们在上篇文章中提到了 RAII 。那么本篇文章会对此进行详解。重点是智能指针的详解。其中会讲解到 RAII 思想、auto_ptr、unique_ptr、shared_ptr、weak_ptr、循环引用问题。希望本篇文章会对你有所帮助。

weixin_67596609的博客 2262

基于STM32L4XX 、HAL库的TMC2226-SA-T步进电机驱动器驱动程序应用设计

集成的功率MOSFET可处理高达2A RMS的电机电流,并具备保护与诊断功能,确保运行稳健可靠。作为业界最先进的STEP/DIR步进电机驱动系列,该芯片通过升级设计实现无噪音、高精度运行,为用户提供高性价比且极具竞争力的解决方案。// 用于PDN_UART单线通信。// HAL_UART_Transmit - 注意PDN_UART是单线,收发共线。.huart = &huart1, // PDN_UART连接的USART。均方根步进/方向控制接口,提供8、16、32或64微步针设置,

PP_Cottage的博客 623

【零基础入门unity游戏开发——unity通用篇12】导入导出unity资源包、设置编程工具、创建脚本(组件)规则、MonoBehaviour基类介绍、脚本模板(基于unity6开发介绍)

导入导出unity资源包、设置编程工具、创建脚本(组件)规则、MonoBehaviour基类介绍、脚本模板(基于unity6开发介绍)

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 760

C++内存列传之RAII宇宙:智能指针

智能指针是 C++ 中用于自动管理动态内存的类模板,它通过 RAII(资源获取即初始化)技术避免手动 new/delete 操作,从而显著减少内存泄漏和悬空指针的风险

Zero_VPN的博客 2785

14 Prompt 的边界:什么时候必须用 RAG 或微调

Prompt 不是万能解法。本文用“改输入、补知识、改模型”这条主线,讲清什么时候继续优化 Prompt,什么时候必须引入 RAG、工具调用或微调,帮助你避免用重技术掩盖轻问题。

老于的笔记的专栏 209

RAII和智能指针的实现

RAII在C++effective一书中讲到,RAII是“Resource acquisition is initialization”,直译为“资源获取就是初始化”。它是基于这样的原理,栈的变量会自动销毁,(自定义类型对象会调用析构函数)。它是将管理资源变为管理对象,将资源封装成类,利用构造函数来获取并初始化资源,析构函数来释放资源,从而保证资源的正确获取,初始化以及释放。从而避免了因此异常等其他

xy913741894的博客 2291

运行openclaw gateway install时出现Gateway install failed: Error: schtasks create failed的解决方案

本文主要介绍了运行openclaw gateway install时出现Gateway install failed: Error: schtasks create failed的解决方案,希望能对学习和使用openclaw的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 11万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【C++】详解RAII思想与智能指针

上一篇关于异常处理的文章,我们提到,异常处理是存在内存泄漏风险的,由于异常捕获会导致程序运行时执行流的跳转,并且在某些资源释放之前就进行了跳转,此时就会引发内存泄漏。什么是内存泄漏呢?内存泄漏是指程序在运行的过程中,动态分配的内存被占用但没有得到释放,从而导致资源不能被回收,最终可能导致系统性能下降甚至崩溃。

谁在夜里看海.的博客 5109

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++11新增特性:智能指针(RAII)

在C++的发展史中,一个出现了4种智能指针,依次为auto_ptr、unique_ptr、shared_ptr、weak_ptr(weak_ptr不符合RAII思想,用于对shared_ptr的补贴)同理,n1的引用计数也更新为2!但是_next属于n2的成员,n1释放了,_next才会析构,而n2由_prev管理,_prev属于n1成员,此时就发生了循环引用,谁也不会释放。weak_ptr不符合RAII,不参与引用计数,仅是对 shared_ptr 所管理对象的一个非拥有性引用,但可以像指针一样使用!

Zhenyu_Coder的博客 1934

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【C++干货铺】 RAII实现智能指针

本篇文章介绍了根据RAII实现的三种智能指针!!!

qq_55119554的博客 1829

多线程拓展—— RAII与 智能指针

在前面的章节中,我们介绍了多线程编程中的基本概念,包括线程的创建、同步、互斥等。在锁的介绍那篇文章中我们介绍了锁的包装器与lock_guard,它们都是基于RAII(Resource Acquisition Is Initialization)原则的智能指针。RAII是一种编程范式,它使用对象的生命周期来管理资源的分配和释放。在多线程编程中,RAII可以有效地避免资源泄露和死锁等问题。而这篇文章我们将从RAII开始,探究c++11后内存管理的一些新特性.

qq_73924465的博客 866

智能指针RAII(C++)

智能指针基于RAII思想,RAII是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。

moran114的博客 1081

智能指针RAII

智能指针的意义;智能指针的的使用场景;智能指针的的历史发展;智能指针的模拟实现;

shylyly_的博客 1033

【C++ 智能指针】RAII和四种智能指针你理解吗?

🐧①RAII机制;🖊🐧②四种智能指针,auto_ptr、unique_ptr、shared_ptr、weak_ptr;🖊

Hou_lang_LJ的博客 736

C++ 中的智能指针和 RAII 机制

RAII 机制、智能指针、unique_ptr、智能指针与 pimpl 惯用法结合

We choose to go to the moon in this decade and do the other things, not because they are easy, but beacase they are hard. 1020

【C++进阶】RAII思想&智能指针

这里我们也就讲完了智能指针了,智能指针还是很实用的。到这里我们C++的大部分重难点也就结束了。如果你到了这里,首先恭喜你坚持学习到了现在并且感受到了C++的独特之处。但是我们的学习还远没有结束,下一节我们会讲解类的设计模式中的常用的模式之一:单例模式。希望大家可以持续关注。

weixin_64906519的博客 1279

C++智能指针(RAII思想)

RAII(资源获取即初始化)是C++的核心编程范式,通过对象生命周期管理资源(内存、文件等)。智能指针(unique_ptr、shared_ptr、weak_ptr)是RAII的典型实现:unique_ptr独占资源且零开销;shared_ptr共享资源但需维护引用计数;weak_ptr解决循环引用问题。

2301_79383371的博客 1046
上一篇: 如何搭建一个个人私服 Git
下一篇: 1.C++编译过程
许菠萝
博客等级 码龄10年 263粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值