赞
踩
众所周知,一个类对象创建会自动调用构造函数,析构会自动调用析构函数。因此我们可以利用此机制自动解决资源的申请和释放问题,例如:
RAII,完整的英文是Resource Acquisition Is Initialization,是C++特有的资源管理方式。在主流的语言中,C++是唯一一个依赖RAII来做资源管理的。RAII依托栈和析构函数,来对所有的资源(包括堆内存在内)进行管理,对RAII的使用,使得C++不需要类似于java那样的垃圾收集方法,也能有效地对内存进行管理。具体而言,C++11的stl中带来了3中智能指针,正确合理的使用可以帮助我们管理资源,当然,在C++中使用智能指针不像在java,python中使用垃圾回收机制那么舒适,毕竟程序员还是需要做一些额外的事情,但这远比原来的C++更加方便。这三种智能指针分别是
首先,如果将指针要申请的资源放在一个类当中的话,在析构的时候可以自动释放资源,我们的简单目的已经达成。相当于这个类管理了一个指针,可以让他自动释放,相当于模拟了char* p=new char[255];
同时也可以自动释放。
#define _crt_secure_no_warnings #include<iostream> #include <cstring> using namespace std; class SmartPtr { private: char* m_Pname; public: SmartPtr(const char*a){ m_Pname = new char[255]; strcpy(m_Pname, a); } ~SmartPtr() { if (m_Pname != nullptr) { delete m_Pname; } } };
上文仅仅模拟了一个指针的动态申请内存,并且可以做到对该指针做自动释放而已,如果要模拟char* m_Pname2=m_Pname呢?
,这条语句m_pname2指向m_Pname指向的一块内存。用类来模拟的话其实就是浅拷贝。可以试验调试下面的程序,不过因为他是浅拷贝,所以析构时会有内存泄漏。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include <cstring> using namespace std; class SmartPtr { private: char* m_Pname; public: SmartPtr(const char* a) { //在构造函数中动态申请m_Pname资源 m_Pname = new char[255]; strcpy(m_Pname, a); } SmartPtr(SmartPtr& obj) { //拷贝构造函数 m_Pname = obj.m_Pname; } SmartPtr& operator=(SmartPtr& obj) { m_Pname = obj.m_Pname; return *this; } ~SmartPtr()//析构函数 { if (m_Pname != nullptr) { delete m_Pname; } } }; int main() { { SmartPtr obj1("张三");//读者可将断点打在此处进行调试进行观察 SmartPtr obj2 = obj1; }//约束在一个块作用域中查看析构 return 0; }
现在obj2对象管理的obj2.m_Pname和obj1.m_Pname就指向了同一块堆内存
但是我们又知道浅拷贝在析构时有重复释放的bug,于是就有了引用计数的想法——每拷贝一个对象,引用计数器加一;每个对象析构的时候要查看引用计数器的值,只有引用计数器的值为1时才释放资源。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include <cstring> using namespace std; class SmartPtr { private: char* m_Pname; int* m_pCount;//引用计数器,注意引用计数器设置为int*变量,这样的话每个对象的都操作的自己的指针变量指向 //的都是同一片内存*m_pCount。不能直接用int类型,而且也不能用static,因为这样的话就相当于只能有一个计数器 //而指针的话我们以后写时拷贝的话可以再申请计数器,这一点介绍到写时拷贝再看就理解了 public: SmartPtr(const char* a) { //在构造函数中动态申请m_Pname资源 m_Pname = new char[255]; m_pCount = new int; strcpy(m_Pname, a); *m_pCount = 1; } SmartPtr(SmartPtr& obj) { //拷贝构造函数 m_Pname = obj.m_Pname; m_pCount = obj.m_pCount; (*m_pCount)++; } SmartPtr& operator=(SmartPtr& obj) { m_Pname = obj.m_Pname; m_pCount = obj.m_pCount; (*m_pCount)++; return *this; } void release() { (*m_pCount)--; if (*m_pCount == 0) { delete m_Pname; } } ~SmartPtr()//析构函数 { release(); } }; int main() { { SmartPtr obj1("张三");//读者可将断点打在此处进行调试进行观察 SmartPtr obj2 = obj1; }//约束在一个块作用域中查看析构 return 0; }
可以再将这个引用计数封装成一个类
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstring>
using namespace std;
struct
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。