1 C++ RAII机制
RAII(Resource Acquisition Is Initialization),资源获取即初始化,是一种C++编程技术。在类的构造函数中请求资源,在类的析构函数中释放资源的技术称为资源获取即初始化,简称RAII。
RAII技术可以将每个资源封装到一个类中,其中
- 构造函数负责获取资源并建立所有类的不变量,如果无法完成则抛出异常
- 析构函数负责释放资源
遵循此种技术规范,可以避免在普通代码中分配内存,把资源分配操作隐藏在构造函数与析构函数中,这样可以避免使用裸new和裸delete操作,使得我们的代码避免因为释放资源而导致内存泄漏的问题。
在C++标准库的设计中,譬如std::string
,std::vector
等遵循RAII设计,另外标准库还提供了几个RAII
包装器用于管理用户的资源,
std::unique_ptr
,std::shared_ptr
智能指针管理动态分配的内存,管理由普通指针表示的任何资源;std::lock_guard
,std::unique_lock
,std::shared_lock
用于管理互斥锁;
下面就是一个典型的遵循RAII机制的C++类代码,
#include <iostream>
#include <string>
class Example
{
public:
Example(int size):m_DataSize(size),m_pData(new double[size])
{
for (int i = 0; i < size; ++i)
{
m_pData[i] = 0.0;
}
std::cout << "构造函数初始化资源" << std::endl;
}
virtual~ Example()
{
delete[] m_pData;
m_DataSize = 0;
std::cout << "析构函数释放资源" << std::endl;
}
private:
double* m_pData;
int m_DataSize;
};
int main()
{
Example example(5);
return 0;
}
如果我们不使用RAII机制设计,会造成什么后果呢?我们看以下的代码
#include <iostream>
#include <string>
#include <assert.h>
void test()
{
double size = 10;
double* array = new double[10];
for (int i = 0; i < size; ++i)
{
array[i] = 0.0;
}
assert(size == 11);
delete[] array;
}
int main()
{
test();
return 0;
}
我们在上述代码中声明了一个10个大小的double型数组,然后给它所有的元素初始化为0.0,在test()
函数的最后一行使用delete[] array
使用数组内存,但是在之前我们使用了一个断言assert(size == 11)
必须要让size == 11
,这显然是不对的,那么程序在运行过程中就在assert
就崩溃了,那么也不会调用delete[] array
释放内存,造成内存泄漏。当然这是一个很简单的程序,所以这种问题也比较容易发现,但是当一个复杂的项目有几万行甚至更多行数时,我们往往会忽略这种问题,从而引发严重的内存泄漏。所以我们这样修改下述代码
#include <iostream>
#include <string>
#include <assert.h>
#include <memory>
void test()
{
double size = 10;
double* array = new double[10];
for (int i = 0; i < size; ++i)
{
array[i] = 0.0;
}
std::unique_ptr<double> p(array);
assert(size == 11);
}
int main()
{
test();
return 0;
}
使用一个std::unique_ptr
对裸指针array
进行包装,这样裸指针的声明周期就由智能指针来控制,就可以避免无法释放内存的问题。
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++ – RAII机制
原文链接:https://www.stubbornhuang.com/2417/
发布于:2022年11月21日 15:29:22
修改于:2023年06月21日 17:50:30
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
50