Thinking in C++ 学习笔记(2)

Thinking in C++ 学习笔记(2)
关于C++ 中的RAII(Resource Acquisition In Initialisation) Wrapper

问题:class的构造函数中如果出现异常而被捕获中止,则对象构造不完整, 相应的析构函数也不会被调用。 如果在构造的异常出现之前已经有指向其它对象的堆指针被实例化, 由于该对象的析构函数
不被调用,而使得对象的堆指针指出的堆内存不被释放。

如:
  1 //: C01:Rawp.cpp
  2 //Naked pointer           
  3 
  4 #include <iostream>       
  5 #include <cstddef>        
  6    
  7 using namespace std;      
  8    
  9 class Cat {
 10 public:                   
 11     Cat() {cout << "Cat ()" << endl;}
 12     virtual ~Cat() {cout << "~Cat()" << endl;}
 13 }; 
 14    
 15 class Dog {
 16 public:
 17     void *operator new(size_t sz) {
 18         cout << "allocating a Dog" << endl; 
 19         throw 47;
 20     }
 21    
 22     void operator delete(void* p) {
 23         cout << "deallocating a Dog" << endl;
 24         ::operator delete(p);
 25     }
 26 };
 27 
 28 class UseResource {
 29     Cat* bp;
 30     Dog* op;
 31 public:
 32     UseResource(int count = 1) {
 33         cout << "UseResources()" << endl;
 34         bp = new Cat[count];
 35         op = new Dog;
 36     }
 37     virtual ~UseResource() {
 38         cout << "~UseResource()" << endl;
 39         delete[] bp;
 40         delete op;
 41     }
 42 };
 43 
 44 int main()
 45 {
 46     try {
 47         UseResource ur(3);
 48     } catch (int) {
 49         cout << "inside handler" << endl;
 50     }
 51 }
解决方法:
1 在构造函数中使用try{} catch() {}捕获异常并且进行处理。
2 将nake pointer的分配内存过程由另外一个对象的构造函数来实现,
而释放内存过程由另外一个对象的析构函数来完成。

对于2的实例如下:
  1 //: C01:Wrapped.cpp
  2 // Saft atomic pointers
  3 
  4 #include <iostream> 
  5 #include <cstddef> 
  6 using namespace std;
  7 
  8 template<class T, int sz = 1>
  9 class PWrap {
 10     T* ptr;
 11 public: 
 12     
 13     class RangeError{};
 14     PWrap() {
 15         ptr = new T[sz];    
 16         cout << "PWrap Constructor" << endl;
 17     }
 18     virtual ~PWrap () {
 19         delete[] ptr;
 20         cout << "PWrap Destructor" << endl; 
 21     }
 22 
 23     T& operator [] (int i) throw (RangeError) {
 24         if (i >= 0 && i < sz) {
 25             return ptr[i];
 26         }
 27         throw RangeError();
 28     }
 29 };
 30 
 31 
 32 class Cat {
 33 public:
 34     Cat() {cout << "Cat()" << endl;}
 35     virtual ~Cat() {cout << "~Cat" << endl;}
 36     void g() {};
 37 };
 38 
 39 class Dog {
 40 public :
 41     void *operator new[] (size_t ) {
 42         cout << "allocating a Dog" << endl;
 43         throw 47;
 44     }
 45 
 46     void operator delete[](void* p) {
 47         cout << "Deallocating a Dog" << endl;
 48         ::operator delete[] (p);
 49     }
 50 };
 51 
 52 class UseResource {
 53     PWrap<Cat, 3> cats;
 54     PWrap<Dog> dog;
 55 public:
 56     UseResource() { cout << "UseResource()" << endl;}
 57     virtual ~UseResource() { cout << "~UseResource()" << endl;}
 58     void f() { cats[1].g();}
 59 };
 60 
 61 int main() {
 62     try {
 63         UseResource ur;
 64     } catch (int) {
 65         cout << "inside handler" << endl;
 66     }
 67 }
在c++中,<memory>中的auto_ptr 就是这样一个RAII Wrapper模板。
其使用方式如下:

  1 //: C01:Auto_ptr.cpp
  2 // auto_ptr template for wrapping raw pointer
  3 
  4 #include <iostream>       
  5 #include <cstddef> //for size_t type
  6    
  7 using namespace std;      
  8    
  9 class TraceHeap {         
 10     int i;                
 11 public:
 12     static void * operator new (size_t size) { 
 13         void * p = ::operator new(size);    
 14         cout << "Allocating TraceHeap object on the heap"
 15              << " at address "
 16              << p << endl;
 17         return p;         
 18     }
 19    
 20     static void operator delete(void* p) {
 21         cout << "Deallocating TraceHeap object at address " 
 22              << p << endl;
 23         ::operator delete(p); 
 24     }                     
 25 
 26     TraceHeap(int i) : i(i) {
 27     
 28     }
 29    
 30     int getVal() const {return i;} 
 31 };
 32    
 33 int main() {
 34     auto_ptr<TraceHeap> pMyObject(new TraceHeap(3));
 35     cout << pMyObject->getVal() << endl;
 36 }  
运行结果:
Allocating TraceHeap object on the heap at address 0x502010
3
Deallocating TraceHeap object at address 0x502010
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值