博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++程序的设计机制3 RAII机制(2)
阅读量:5805 次
发布时间:2019-06-18

本文共 2336 字,大约阅读时间需要 7 分钟。

C++程序的设计机制3 RAII机制(2)

为了管理内存等资源,C++程序员通常采用RAII机制(资源获取即初始化),在使用资源的类的构造函数中申请资源,然后使用,最后在析构函数中释放资源。今天本文为你介绍RAII机制,一起来看。

AD:

2)智能指针模拟

一个更复杂一点的例子是模拟智能指针,抽象出来的RAII类中实现了一个操作符*,直接返回存入的指针:

现在我们有一个类:

  1. class Example {  
  2. SomeResource* p_;  
  3. SomeResource* p2_;  
  4. public:  
  5. Example() :  
  6. p_(new SomeResource()),  
  7. p2_(new SomeResource()) {  
  8. std::cout << "Creating Example, allocating SomeResource!\n";  
  9. }  

10.Example(const Example& other) :  

11.p_(new SomeResource(*other.p_)),  

12.p2_(new SomeResource(*other.p2_)) {}  

13.Example& operator=(const Example& other) {  

14.// Self assignment?  

15.if (this==&other)  

16.return *this;  

17.*p_=*other.p_;  

18.*p2_=*other.p2_;  

19.return *this;  

20.}  

21.~Example() {  

22.std::cout << "Deleting Example, freeing SomeResource!\n";  

23.delete p_;  

24.delete p2_;  

25.}  

26.}; 

假设在创建SomeResource的时候可能会有异常,那么当p_指向的资源被创建但p2_指向的资源创建失败时,Example的实例就整个创建失败,那么p_指向的资源就存在内存泄露问题。

用下边的这个方法可以为权宜之计:

  1. Example() : p_(0),p2_(0)  
  2. {  
  3. try {  
  4. p_=new SomeResource();  
  5. p2_=new SomeResource("H",true);  
  6. std::cout << "Creating Example, allocating SomeResource!\n";  
  7. }  
  8. catch(...) {  
  9. delete p2_;  

10.delete p_;  

11.throw;  

12.}  

13.} 

但是我们可以利用一个对象在离开一个域中会调用析构函数的特性,在构造函数中完成初始化,在析构函数中完成清理工作,将需要操作和保护的指针作为成员变量放入RAII中。

  1. template   
  2. class RAII {  
  3. T* p_;  
  4. public:  
  5. explicit RAII(T* p) : p_(p) {}  
  6. ~RAII() {  
  7. delete p_;  
  8. }  
  9. void reset(T* p) {  

10.delete p_;  

11.p_=p;  

12.}  

13.T* get() const {  

14.return p_;  

15.}  

16.T& operator*() const {  

17.return *p_;  

18.}  

19.void swap(RAII& other) {  

20.std::swap(p_,other.p_);  

21.}  

22.private:  

23.RAII(const RAII& other);  

24.RAII& operator=(const RAII& other);  

25.}; 

我们在具体使用把保护的指针Someresource放在RAII中:

  1. class Example {  
  2. RAII p_;  
  3. RAII p2_;  
  4. public:  
  5. Example() :  
  6. p_(new SomeResource()),  
  7. p2_(new SomeResource()) {}  
  8. Example(const Example& other)  
  9. : p_(new SomeResource(*other.p_)),  

10.p2_(new SomeResource(*other.p2_)) {}  

11.Example& operator=(const Example& other) {  

12.// Self assignment?  

13.if (this==&other)  

14.return *this;  

15.*p_=*other.p_;  

16.*p2_=*other.p2_;  

17.return *this;  

18.}  

19.~Example() {  

20.std::cout << "Deleting Example, freeing SomeResource!\n";  

21.}  

22.}; 

现在即使p_成功而p2_失败,那么在Stack winding时也会调用RAII的析构函数保证了p_指向的Someresource被析构。这种方法较之例1中需要实现被组合的指针类型相应的接口不 同,这里不需要对接口进行封装。当然,在例1中,你也可以提供一个getPointer的函数直接将句柄提供出来。

其实在Example中,已经不需要析构函数了,因为RAII类会帮它照顾好这一切的。这有点像auto_ptr,本文并不打算深入讨论智能指针这个话题。参考资料

转载于:https://www.cnblogs.com/Q685656/archive/2013/01/30/2882477.html

你可能感兴趣的文章
初探 JavaScript 的变量
查看>>
javaScript高阶级函数
查看>>
webpack系列-插件机制杂记
查看>>
Android技术栈总结
查看>>
18年总结
查看>>
【收藏干货】axios配置大全
查看>>
如何快速学习Java?
查看>>
91. Decode Ways
查看>>
219. Contains Duplicate II
查看>>
215. Kth Largest Element in an Array
查看>>
1154 Vertex Coloring (25 分)
查看>>
防抖动与节流
查看>>
JavaScript对象的深入理解(二)
查看>>
差分隐私学习总结
查看>>
【266天】跃迁之路——程序员高效学习方法论探索系列(实验阶段24-2017.10.29)...
查看>>
【自己读源码】Netty4.X系列(一) 启动类概览
查看>>
React全家桶框架兼容IE8教程
查看>>
Python学习小结---if语句
查看>>
处理for-in用在数组上时候出现的诡异现象的问题
查看>>
详解 Weex 页面的渲染过程
查看>>