当前位置: 首页 > news >正文

网站建设南京长沙疫情最新数据消息

网站建设南京,长沙疫情最新数据消息,嘉兴网站关键词排名,怎么做期货网站🌈 个人主页:谁在夜里看海. 🔥 个人专栏:《C系列》《Linux系列》 ⛰️ 丢掉幻想,准备斗争 目录 引言 内存泄漏 内存泄漏的危害 内存泄漏的处理 一、RAII思想 二、智能指针 1.auto_ptr 实现原理 模拟实现 弊端…

75e194dacf184b278fe6cf99c1d32546.jpeg

🌈 个人主页:谁在夜里看海.

🔥 个人专栏:《C++系列》《Linux系列》

⛰️ 丢掉幻想,准备斗争

d047c7b1ef574257b8397fe5cc5c290b.gif

目录

引言

内存泄漏

内存泄漏的危害

内存泄漏的处理

一、RAII思想

二、智能指针

1.auto_ptr

实现原理

模拟实现

弊端

2.unique_ptr

实现原理

模拟实现

3.shared_ptr

实现原理

模拟实现

循环引用问题

4.weak_ptr


引言

上一篇关于异常处理的文章,我们提到,异常处理是存在内存泄漏风险的,由于异常捕获会导致程序运行时执行流的跳转,并且在某些资源释放之前就进行了跳转,此时就会引发内存泄漏,来看下面这段代码:

当我输入3 0时,程序会抛出除零错误,并跳过了 delete p1; delete p2; 语句,因为异常发生时,程序的执行流会跳转到 catch 块,导致析构函数没有执行,引发内存泄漏。

内存泄漏

什么是内存泄漏呢?内存泄漏是指程序在运行的过程中,动态分配的内存被占用但没有得到释放,从而导致资源不能被回收,最终可能导致系统性能下降甚至崩溃

内存泄漏的危害

1.如果内存泄漏非常严重,程序将消耗所有的可用内存,导致操作系统或程序本身的崩溃。

2.内存泄漏意味着分配的内存空间无法被回收,不仅浪费内存空间,还可能会影响其他进程。

3.在一些长期运行的系统(服务器、嵌入式设备等)中,内存泄漏会导致系统持续消耗内存而不释放,久而久之会导致系统性能下降并最终导致系统崩溃。

4.内存泄漏往往是隐蔽性的,在大规模且复杂的程序中,调试和定位内存泄漏非常困难,这时可能需要借助一些外部的工具。

内存泄漏的处理

一般分为两种:事先预防型 事后查错型

事后查错型例如借助外部工具;

我们下面要介绍的就是对内存泄漏的事先预防处理办法,采用RAII思想以及智能指针:

一、RAII思想

RAII 全称 Resource Acquisition Is Initialization,中文翻译:资源获取即初始化,它强调通过对象的生命周期来管理资源,将资源的获取与释放与对象的创建与销毁相一致,RAII设计原则可以更好地管理动态资源,有效避免内存泄漏。还是用上述例子来直观感受一下:

template<class T>
class smartptr {
public:smartptr(T data){cout << "smartptr(T data)" << endl;_ptr = new T(data);}~smartptr(){cout << "~smartptr()" << endl;delete _ptr;}private:T* _ptr;
};int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0错误");return a / b;
}
int main()
{try{smartptr<int> p1(1);smartptr<int> p2(2);div();}catch (exception& e){cout << e.what() << endl;}return 0;
}

我们可以看到,RAII思想实际上就是将资源的获取与释放封装到一个类中,在构造函数中获取资源,在析构函数中释放资源。我们不需要显式地释放资源,并且将资源与对象的生命周期绑定

输入3 0时,抛出除零异常,执行流跳转的同时,try块内部生命周期结束,此时会调用内部对象的析构函数,完成了资源的释放,避免了资源泄露。

二、智能指针

上述smartptr还不能被称作智能指针,因为它不具备指针的行为,我们还需要在类内部重载解引用*、访问->等操作,使其能像指针一样使用:

template<class T>
class smartptr {
public:smartptr(T data = T()){_ptr = new T(data);}~smartptr(){delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};struct Date {int _year;int _month;int _day;
};int main()
{smartptr<Date> p1;p1->_year = 2024;p1->_month = 11;p1->_day = 9;cout << (*p1)._year << "-" << (*p1)._month << "-" << (*p1)._day << endl;return 0;
}

智能指针采用RAII原理来管理动态分配的内存,也是将资源的管理与对象的生命周期绑定,并且可以像普通指针那样进行*、->等操作。

下面我们来介绍一下C++98提供的auto_ptr智能指针:

1.auto_ptr

auto_ptr是C++98标准引入的一种智能指针,是RAII思想的体现,其核心功能是自动管理动态分配的内存,确保指针在超出作用域时,资源被正确释放,下面是它的主要实现原理:

实现原理

构造函数

auto_ptr的构造函数接受一个原始指针(裸指针),并将其封装成auto_ptr对象内部的指针:

auto_ptr<int> p(new int(10)); // 构造函数

析构函数

auto_ptr的析构函数会在对象生命周期结束时自动调用delete操作符,释放指针所指向的内存:

~auto_ptr() {delete _ptr;  // 释放内存
}

拷贝构造函数

与普通对象的拷贝构造函数不同,auto_ptr在拷贝时会转移其资源所有权给新对象。因此,拷贝构造后,原对象会变成一个空指针(指向nullptr) 

auto_ptr(const auto_ptr& other) : _ptr(other._ptr) {other._ptr = nullptr;  // 将原对象的指针设为 nullptr,避免重复释放
}

赋值操作符

auto_ptr的赋值操作符也会转移资源所有权,先释放当前对象的资源,然后将传入的指针复制到当前对象,并将传入指针置空:

auto_ptr& operator=(const auto_ptr& other) {if (this != &other) {delete _ptr;  // 先释放当前资源_ptr = other._ptr;other._ptr = nullptr;  // 将 other 的指针置空}return *this;
}

成员访问

通过重载*、->实现指针的解引用与访问成员操作:

auto_ptr<int> p(new int(10));
*p = 20;  // 访问值
模拟实现

下面是对auto_ptr的简单模拟实现:

	template<class T>class auto_ptr{public:// 构造函数auto_ptr(T* ptr):_ptr(ptr){}// 拷贝构造函数auto_ptr(auto_ptr<T>& other):_ptr(other._ptr){// 管理权转移other._ptr = nullptr;}// 赋值函数auto_ptr operator=(const auto_ptr<T> other){// 检测是否给自己赋值if (*this != other){// 释放当前资源if (_ptr)delete _ptr;_ptr = other._ptr;other._ptr = nullptr;}return *this;}// 析构函数~auto_ptr(){if(_ptr)delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
弊端

auto_ptr在拷贝和赋值时隐式地转移了资源所有权,会导致一些潜在的资源管理问题。

auto_ptr被拷贝时,源对象指针被置空,此时无法再进行访问

auto_ptr<int> p1(new int(10));  // 创建 p1
auto_ptr<int> p2 = p1;          // p1 的资源转移给 p2,p1 变为 nullptr
cout << *p1 << std::endl;       // 错误,p1 已为空指针

这种隐性的资源转移,使得auto_ptr在传递和返回时不直观,比如,我们在函数调用对象时,希望资源可以被复制并共享,但是auto_ptr不允许资源的共享,可能会导致意料之外的资源转移

void foo(auto_ptr<int> ptr) {// ptr 的资源所有权已经转移到 foo 函数的局部变量中
}int main() {auto_ptr<int> p1(new int(10));foo(p1);  // p1 的资源被转移到 foo,p1 变为空指针cout << *p1 << std::endl;  // 错误,p1 已为空指针
}

auto_ptr在实际使用过程中,会引发许多不易察觉的错误,这并不是我们想要的智能指针,为了避免上述问题,C++11引入了更多新的智能指针,例如unique_ptr:

2.unique_ptr

为了避免所有权转移导致的一系列潜在问题,unique_ptr采用了一种简单粗暴的办法:禁止拷贝,禁止一切拷贝行为,从根源上解决了问题。

实现原理

禁止拷贝行为
编译器会禁止unique_ptr的拷贝构造与拷贝复制操作,试图拷贝将会报错:

std::unique_ptr<int> p1(new int(10));
// 编译错误,禁止拷贝构造
std::unique_ptr<int> p2 = p1; // 错误:拷贝构造被删除

明确的资源所有权转移

禁止拷贝并不意味着对资源所有权转移的全面封杀,实际上还是可以对资源进行转移的,只不过auto_ptr是隐式地转移,而unique_ptr是显式地进行转移:

unique_ptr<int> p1(new int(10));
unique_ptr<int> p2 = move(p1); // 明确转移资源所有权// p1 现在为空指针,p2 拥有资源
cout << *p2 << endl;  // 输出 10
// cout << *p1 << endl; // 错误:p1 现在为空指针
模拟实现

那么unique_ptr在底层是怎么实现对拷贝的禁止的呢,其实是用到了delete关键字,在成员函数后面加上 = delete,表示禁止该成员函数的使用,通过delete删除拷贝构造函数与拷贝赋值函数,从而禁止了拷贝行为的发生:

	template<class T>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}~unique_ptr(){if (_ptr)delete _ptr;}// 指针操作T& operator*(){return *_ptr;}T* operator->(){return _ptr;}// 不支持拷贝构造、拷贝赋值unique_ptr(const unique_ptr<T>& other) = delete;unique_ptr operator=(const unique_ptr<T> other) = delete;private:T* _ptr;};

C++11还提供了一种智能指针,它支持拷贝行为,并且允许多个对象共享资源,即拷贝赋值并不会将原指针置空,而是让它们指向同一块空间:

3.shared_ptr

shared_ptr支持拷贝构造以及拷贝赋值,它们可以共享资源,各自进行操作,但要考虑一个问题:RAII的思想是将资源的获取和释放与对象的生命周期绑定,当我通过函数传参的方式将一个对象赋值给了另一个对象,会导致资源的提前释放(函数结束),这样外部指针就悬空了,共享的资源只需要进行一次释放即可,那么我们怎么知道何时释放资源呢?通过计数器的方式实现:

实现原理

shared_ptr通过引用计数来实现资源的正确释放,确保在所有共享该资源的shared_ptr对象都销毁后才释放资。 

当另一个shared_ptr对象拷贝构造或者赋值时,引用计数增加,表示多了一个对象在共享资源;当shared_ptr对象析构或被赋值到新的对象时,引用计数减少,表示减少一个共享资源的持有者。

模拟实现

实现过程如下:

	template<class T>class shared_ptr{public:shared_ptr(T* ptr):_ptr(ptr),_pCount(new int(0)){++* _pCount; // 增加计数}shared_ptr(shared_ptr<T>& other):_ptr(other._ptr),_pCount(other._pCount){cout << "shared_ptr(shared_ptr<T>& other)" << endl;++* _pCount; // 增加计数}shared_ptr operator=(shared_ptr<T>& other){// 检测是否给自己赋值if (_ptr  != other._ptr){cout << "shared_ptr operator=(const shared_ptr<T>& other)" << endl;--* _pCount; // 减少当前资源的计数// 释放当前资源if (*_pCount == 0){delete _ptr;delete _pCount;}_ptr = other._ptr;_pCount = other._pCount;++* _pCount; // 增加新资源的计数}return *this;}~shared_ptr(){--* _pCount; // 减少计数if (*_pCount == 0){// 共享对象全部销毁,进行析构cout << "~shared_ptr()" << endl;delete _ptr;delete _pCount;}}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;int* _pCount;};

shared_ptr适用于绝大多数场景,但是在某些场景下,会引发循环引用问题,此时资源不能得到正确释放:

循环引用问题

来看下面这段代码:

struct ListNode
{int _data;shared_ptr<ListNode> _prev;shared_ptr<ListNode> _next;~ListNode() { cout << "~ListNode()" << endl; }
};
int main()
{shared_ptr<ListNode> node1(new ListNode);shared_ptr<ListNode> node2(new ListNode);cout << node1.use_count() << endl;cout << node2.use_count() << endl;node1->_next = node2;node2->_prev = node1;cout << node1.use_count() << endl;cout << node2.use_count() << endl;return 0;
}

我们将节点的_prev和_next定义成shared_ptr智能指针,并定义了两个节点,节点2的_prev指向节点1,节点1的_next指向节点2:

这个时候会造成什么结果呢,我们来看运行结果:

node1的_next和node2共享资源,所以它们的计数为2,node2的_prev和node1共享资源,所以它们的计数也为2,从运行结果可以看出,节点空间没有得到释放(没有打印"~ListNode()"内容),这是为什么呢?

由于Node1和Node2的相互引用,它们的任意一个要想释放空间,都得建立在对方已经释放空间的基础上,于是乎两者都不能正常进行空间释放,这就是循环引用问题。

4.weak_ptr

C++11提供了一种弱引用智能指针weak_ptr,它的出现就是为了解决循环引用问题的,其原理是:weak_ptr是对对象的弱引用,不会增加计数,不会阻止资源的释放

由于互相指向时,计数没有增加,所以最后析构函数正常调用,资源得到释放。


以上就是对RAII思想及智能指针的介绍与个人理解,欢迎指正~ 

码文不易,还请多多关注支持,这是我持续创作的最大动力!


文章转载自:
http://wanjiascolopophorous.mdwb.cn
http://wanjiadiacidic.mdwb.cn
http://wanjiaminicoy.mdwb.cn
http://wanjiasympathetic.mdwb.cn
http://wanjiabuck.mdwb.cn
http://wanjiainterlinear.mdwb.cn
http://wanjiaoriental.mdwb.cn
http://wanjiatychism.mdwb.cn
http://wanjiajoad.mdwb.cn
http://wanjiaenroll.mdwb.cn
http://wanjiasestertii.mdwb.cn
http://wanjiacomparably.mdwb.cn
http://wanjiapaleencephalon.mdwb.cn
http://wanjiaanalgetic.mdwb.cn
http://wanjiaadynamic.mdwb.cn
http://wanjiaconstringe.mdwb.cn
http://wanjiatutty.mdwb.cn
http://wanjiagunther.mdwb.cn
http://wanjiaapplausive.mdwb.cn
http://wanjiasloping.mdwb.cn
http://wanjiadnase.mdwb.cn
http://wanjiaestablishment.mdwb.cn
http://wanjiapdm.mdwb.cn
http://wanjiaanhidrosis.mdwb.cn
http://wanjiasynoecete.mdwb.cn
http://wanjiacalisaya.mdwb.cn
http://wanjiajudicable.mdwb.cn
http://wanjiatransmutability.mdwb.cn
http://wanjiaslickster.mdwb.cn
http://wanjiapuddly.mdwb.cn
http://wanjiaundersheriff.mdwb.cn
http://wanjiagrandiloquent.mdwb.cn
http://wanjialoquitur.mdwb.cn
http://wanjiashelterbelt.mdwb.cn
http://wanjiadiphyodont.mdwb.cn
http://wanjiaecru.mdwb.cn
http://wanjiapolypoid.mdwb.cn
http://wanjiachirpy.mdwb.cn
http://wanjiatumescent.mdwb.cn
http://wanjiagiber.mdwb.cn
http://wanjiaaerotherapeutics.mdwb.cn
http://wanjialevulose.mdwb.cn
http://wanjiastomacher.mdwb.cn
http://wanjiagalenobismutite.mdwb.cn
http://wanjiaavoidant.mdwb.cn
http://wanjiagerontology.mdwb.cn
http://wanjiashipfitter.mdwb.cn
http://wanjiaheartwood.mdwb.cn
http://wanjiagreenfinch.mdwb.cn
http://wanjiasprung.mdwb.cn
http://wanjiasylvics.mdwb.cn
http://wanjiapolycystic.mdwb.cn
http://wanjiastormful.mdwb.cn
http://wanjiasynanthy.mdwb.cn
http://wanjiaradioscopically.mdwb.cn
http://wanjiapavement.mdwb.cn
http://wanjiasupernaturally.mdwb.cn
http://wanjiakodacolor.mdwb.cn
http://wanjiawhitey.mdwb.cn
http://wanjiaetyma.mdwb.cn
http://wanjiaechinococci.mdwb.cn
http://wanjiamournfully.mdwb.cn
http://wanjiagraphitoid.mdwb.cn
http://wanjiacindery.mdwb.cn
http://wanjiamissouri.mdwb.cn
http://wanjiaphotodiode.mdwb.cn
http://wanjiawilkes.mdwb.cn
http://wanjiablat.mdwb.cn
http://wanjiahypermarket.mdwb.cn
http://wanjiaaquarian.mdwb.cn
http://wanjiaruthlessly.mdwb.cn
http://wanjiafelty.mdwb.cn
http://wanjiacoelentera.mdwb.cn
http://wanjiavigorously.mdwb.cn
http://wanjiasnorty.mdwb.cn
http://wanjiasedateness.mdwb.cn
http://wanjiasubjectivism.mdwb.cn
http://wanjiaretired.mdwb.cn
http://wanjiasmacksman.mdwb.cn
http://wanjiareveler.mdwb.cn
http://www.15wanjia.com/news/123017.html

相关文章:

  • 自己怎么做外贸批发网站网站建设的推广渠道
  • 武汉营销型网站app引导页模板html
  • 网站域名有哪些河南网络推广公司
  • 百度首页纯净版怎么设置杭州seo俱乐部
  • 企业网站备案费用seo云优化软件破解版
  • 网站模板选择百度关键词优化技巧
  • 高校财务网站建设win10优化大师有用吗
  • 武汉网站策划公司企业建站要多少钱
  • ppt模板设计重庆网站关键词排名优化
  • 深圳珠宝品牌网站设计网站优化seo是什么
  • 做网站需要发票吗手机百度关键词优化
  • 网站投稿源码百度关键词搜索热度
  • 学做网站课程泉州seo代理计费
  • 上门做网站哪家好口碑营销的概念
  • 做网站平台的注册什么商标seo关键词优化系统
  • 北京龙鼎网站建设公司营销推广策划
  • 做胃镜多少钱那好天津津门网站ait培训机构排行榜
  • 中国纪检监察报电子报刊seo关键字优化软件
  • 建站工具word网络优化是干什么的
  • 网站建设保教新闻网站排行榜
  • 去掉wordpress标题中竖线seo和sem的联系
  • 建筑工程机械人才培训网的证书seo新手入门教程
  • 源码购买网站站长工具seo综合
  • html网站 怎么做seo推广普通话手抄报简单
  • 影视网站如何做网络营销课程学什么
  • 怎么直接用代码做网站百度精简版网页入口
  • 精美手机网站模板运营网站
  • 湘潭网站建设 尖端磐石网络推广代理平台登录
  • 可靠的镇江网站建设十大搜索引擎
  • 北京网站建设华网天下定制英文谷歌seo