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
当前分类随机文章推荐
- C++ - std::vector初始化方式总结 阅读110次,点赞0次
- C++ - 我的代码风格/代码规范备忘 阅读1099次,点赞0次
- C++11 - std::string - stod/stof/stoi/stol/stold/stoll/stoul/stoull,由std::string转换为int/long/float/double等其他类型 阅读4327次,点赞0次
- C++ – 字节数组byte[]或者unsigned char[]与float的相互转换 阅读2957次,点赞0次
- C++STL容器 – std::vector容器修改、元素操作总结 push_back,emplace_back,emplace,insert,erase,pop_back,clear,resize,swap 阅读1312次,点赞1次
- C++ - Asio和Boost.Asio的区别 阅读330次,点赞0次
- C++ - Jni中的GetByteArrayElements和GetByteArrayRegion的区别和使用示例 阅读4627次,点赞0次
- C++ - 跨平台在Windows、Linux系统上获取当前可执行程序路径 阅读70次,点赞0次
- C++ – 字节数组byte[]或者unsigned char[]与long double的相互转换 阅读1300次,点赞0次
- C++ - const_cast, static_cast, dynamic_cast, reinterpret_cast四种cast转换的区别和使用 阅读109次,点赞0次
全站随机文章推荐
- 资源分享 - Principles of Digital Image Synthesis , Volume 1 and Volume 2 英文高清PDF下载 阅读1893次,点赞0次
- WordPress - 应对暴力破解登录和规避DDOS的几种方法 阅读2623次,点赞0次
- 资源分享 - The HDRI Handbook- High Dynamic Range Imaging for Photographers and CG Artists英文高清PDF下载 阅读2794次,点赞0次
- 资源分享 - Quaternions for Computer Graphics , Second Edition 英文高清PDF下载 阅读1260次,点赞0次
- Duilib - 使用Default设置控件默认的全局样式以及使用Style自定义样式 阅读264次,点赞0次
- 移动端Android/ios深度学习模型部署框架总结 阅读968次,点赞0次
- 资源分享 - Introduction to 3D Game Programming with DirectX 9.0 英文高清PDF下载 阅读1326次,点赞0次
- 深度学习 - 在大数据集下,内存容量与磁盘IO速度影响模型训练速度的问题 阅读361次,点赞0次
- Python - 使用命令行调用ffmpeg修改视频帧率,将60FPS的视频修改为30FPS的视频,视频时间保持不变 阅读1111次,点赞0次
- 资源分享 - GPU Pro 5 - Advanced Rendering Techniques 英文高清PDF下载 阅读3527次,点赞0次
评论
169