zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    扩展LVM 逻辑卷存储空间
    Linux Shell远程执行命令(命令行与脚本方式)
    vsftpd FTP服务器配置
    初识小米Minos
    使用Libpng库实现Tiny6410显示PNG图片
    uCos-II内存管理
    应用程序调用tslib出现segmentation fault
    Linux-2.6.39在Tiny6410上的移植
    Linux-2.6.39在Tiny6410上的移植
    Tiny6410移植tslib
  • 原文地址:https://www.cnblogs.com/yuboyue/p/2109878.html
Copyright © 2011-2022 走看看