文章目录
我们知道,资源的使用一般经历三个步骤
a.获取资源
b.使用资源
c.销毁资源
资源的销毁往往是程序员经常忘记的一个环节,忘记销毁资源可能会造成内存泄露,怎么解决呢?——RAII
RAII:Resource Acquisition Is Initialization,资源获取即初始化,
RAII的核心思想是:将资源释放操作放在析构函数中,利用C++对象销毁时会自动调用析构函数的特性来保证一定会释放资源,避免内存泄露。
实际做法:我们可以把资源用类进行封装起来,把资源操作都封装在类的内部,在析构函数中进行释放资源。当定义的局部变量的生命结束时,它的析构函数就会自动的被调用,如此,就不用程序员显示的去调用释放资源的操作了。
举例:
下面是不使用RAII(没有使用类的思想)的代码
#include <iostream>
using namespace std;
bool OperationA();
bool OperationB();
int main()
{
int *testArray = new int [10];
// Here, you can use the array
if (!OperationA())
{
// If the operation A failed, we should delete the memory
delete [] testArray;
testArray = NULL ;
return 0;
}
if (!OperationB())
{
// If the operation A failed, we should delete the memory
delete [] testArray;
testArray = NULL ;
return 0;
}
// All the operation succeed, delete the memory
delete [] testArray;
testArray = NULL ;
return 0;
}
bool OperationA()
{
// Do some operation, if the operate succeed, then return true, else return false
return false ;
}
bool OperationB()
{
// Do some operation, if the operate succeed, then return true, else return false
return true ;
}
可以看到,delete [] testArray; 是很容易忘的,一旦忘了就会导致内存泄漏
再看使用RAII 机制的代码:
#include <iostream>
using namespace std;
class ArrayOperation
{
public :
ArrayOperation()
{
m_Array = new int [10];
}
void InitArray()
{
for (int i = 0; i < 10; ++i)
{
*(m_Array + i) = i;
}
}
void ShowArray()
{
for (int i = 0; i <10; ++i)
{
cout<<m_Array[i]<<endl;
}
}
~ArrayOperation() //在析构函数中释放资源
{
cout<< "~ArrayOperation is called" <<endl;
if (m_Array != NULL )
{
delete[] m_Array;
m_Array = NULL ;
}
}
private :
int *m_Array;
};
bool OperationA();
bool OperationB();
int main()
{
ArrayOperation arrayOp;
arrayOp.InitArray();
arrayOp.ShowArray();
return 0;
}
当main函数执行完成之后,arrayOp对象会调用析构函数进行销毁,所以在其析构函数中关闭非栈上资源可以有效防止内存泄露。