C++深度探索系列:智能指针(Smart Pointer)


看原帖
http://www.360doc.com/content/13/0307/12/11715662_269843252.shtml

主题索引:
一、剖析C++标准库智能指针(std::auto_ptr)
    
    1.Do you Smart Pointer?
    2.std::auto_ptr的设计原理
    3.std::auto_ptr高级使用指南
    4.你是否觉得std::auto_ptr还不够完美?
二、C++条件,寻找构造更强大的智能指针(Smart Pointer)的
    策略
    
    1.支持引用记数的多种设计策略
    2.支持处理多种资源
    3.支持Subclassing
    4.支持多线程条件下,线程安全的多种设计策略
    5.其它多种特殊要求下,再构造
三、Generic Programming基础技术和Smart Pointer
    1.回首处理资源中的Traits技术
    2.回首多线程支持的设计

四、COM实现中,Smart Pointer设计原理

五、著名C++库(标准和非标准)中的Smart Pointer现状
---------------------------------------------------------------------

一、剖析C++标准库智能指针(std::auto_ptr)
    
    1.Do you Smart Pointer?
      Smart Pointer,中文名:智能指针, 舶来品?
      不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收
      机制(Garbage Collection)一时颇受注目.然而垃圾自动回收机制并不能
      满足内存管理的即时性和可视性,往往使高傲的程序设计者感到不自在.
      况且,C++实现没有引入这种机制.在探索中,C++程序员创造了锋利的
      "Smart Pointer".一定程度上,解决了资源泄露问题.
      也许,经常的,你会写这样的代码:
      //x拟为class:
      //            class x{
      //            public:        
      //                   int m_Idata;
      //            public:
      //                   x(int m_PARAMin):m_Idata(m_PARAMin){}
      //                   void print(){ cout<      //            .....
      //            }
      //
      void fook(){
      x* m_PTRx = new A(m_PARAMin);
      m_PTRx->DoSomething();     //#2
      delete m_PTRx;
      }
      是的,这里可能没什么问题.可在复杂、N行、m_PTRclassobj所指对象生命周
      期要求较长的情况下,你能保证你不会忘记delete m_PTRclassobj吗?生活中,
      我们往往不应该有太多的口头保证,我们需要做些真正有用的东西.还有一个
      更敏感的问题:异常.假如在#2方法执行期异常发生,函数执行终止,那么new
      出的对象就会泄露.于是,你可能会说:那么就捕获异常来保证安全性好了.
      你写这样的程式:
      void fook(){
      A* m_PTRx = new A(m_PARAMin);
      try{
          m_PTRx->DoSomething();
      }
      catch(..){
          delete m_PTRx;
          throw;
      }
      delete m_PTRx;
      }
      哦!天哪!想象一下,你的系统,是否会象专为捕获异常而设计的.
      一天,有人给你建议:"用Smart Pointer,那很安全.".你可以这样重写你的程序:
    
      void fook(){
      auto_ptr m_SMPTRx(new x(m_PARAMin));
      m_SMPTRx->DoSomething();
      }
      OK!你不太相信.不用delete吗?
      是的.不用整天提心吊胆的问自己:"我全部delete了吗?",而且比你的delete
      策略更安全.
      然后,还有人告诉你,可以这样用呢:
      ok1.
      auto_ptr m_SMPTR1(new x(m_PARAMin)); 
      auto_ptr m_SMPTR2(m_SMPTR1);  //#2
      May be you can code #2 like this :
          auto_ptr m_SMPTR2;
          m_SMPTR2 = m_SMPTR1;      
      ok2.
      auto_ptr m_SMPTR1(new int(32));
      
      ok3.
      auto_ptr m_SMPTR1;
      m_SMPTR1 = auto_ptr(new int(100));
      也可以:
      auto_ptr m_SMPTR1(auto_ptr(new int(100)));
      
      ok4.
      auto_ptr m_SMPTR1(new x(m_PARAMin));
      m_SMPTR1.reset(new x(m_PARAMin1));
      
      ok5.
      auto_ptr m_SMPTR1(new x(m_PARAMin));
      auto_ptr m_SMPTR2(m_SMPTR.release());
      cout<<(*m_SMPTR2).m_Idata<      
      ok6.
      auto_ptr fook(){
      return auto(new int(100));
      }
 
      ok7.............and so on
      
      但不可这样用:
      
      no1.   
      char* chrarray = new char[100];
      strcpy(chrarray,"I am programming.");
      auto_ptr m_SMPTRchrptr(chrarray);
      //auto_ptr并不可帮你管理数组资源     
       
      no2.
      vector> m_VECsmptr;
      m_VECsmptr.push_back(auto_ptr(new int(100)));
      //auto_ptr并不适合STL内容.
       
      no3.
      const auto_ptr m_SMPTR1(new x(100));
      auto_ptr m_SMPTR(new x(200));
      
      no4.
      x m_OBJx(300);
      auto_ptr m_SMPTR(&m_OBJx);
      
      no5
      x* m_PTR = new x(100);
      auto_ptr m_SMPTR = m_pTR;
      
      no6..........and so on
      预先提及所有权的问题,以便下面带着疑问剖析代码?
      power1.
      auto_ptr m_SMPTR1(new x(100));
      auto_ptr m_SMPTR2 = m_SMPTR1;
      m_SMPTR2->print();
      //输出:100.
      m_SMPTR1->print();
      //!! 非法的.
      power2.
      auto_ptr m_SMPTR(new x(100));
      
      auto_ptr returnfun(auto_ptr m_SMPTRin){
      return m_SMPTRin;
      }
      
      auto_ptr = returnfun(m_SMPTR);  //#5
      //在上面的#5中,我要告诉你对象所有权转移了两次.
      //什么叫对象所有权呢?
   
    2. std::auto_ptr的设计原理
       
      上面的一片正确用法,它们在干些什么?
            一片非法,它们犯了什么罪?
            一片什么所有权转移,它的内部机智是什么?
      哦!一头雾水?下面我们就来剖析其实现机制.
      基础知识:
              a.智能指针的关键技术:在于构造栈上对象的生命期控制
                堆上构造的对象的生命期.因为在智能指针的内部,存储
                着堆对象的指针,而且在构析函数中调用delete行为.
                大致机构如下:
                x* m_PTRx = new x(100);//#1
                template
                auto_ptr{
                private:
                T* m_PTR;//维护指向堆对象的指针,在auto_ptr定位后     
                ....     //它应该指向#1构造的对象,即拥有所有权.
                ~auto(){ delete m_PTR; }
                ....
                }
             b.所有权转移之说
               上面曾有一非法的程式片段如下:
               auto_ptr m_SMPTR1(new x(100));
               auto_ptr m_SMPTR2 = m_SMPTR1;
               m_SMPTR2->print();
               //输出:100.
               m_SMPTR1->print();
               //!! 非法的.
               按常理来说,m_SMPTR->print();怎么是非法的呢?
               那是因为本来,m_SMPTR1维护指向new x(100)的指针,
               可是m_SMPTR2 = m_SMPTR1;auto_ptr内部机制使得m_SMPTR1将对象的地址
               传给m_SMPTR2,而将自己的对象指针置为0.
               那么自然m_SMPTR->print();失败.
               这里程序设计者要负明显的职责的.
               那么auto_ptr为什么采取这样的策略:保证所有权的单一性.
                                               亦保证了系统安全性.
               如果多个有全权的auto_ptr维护一个对象,那么在你消除一个
               auto_ptr时,将导致多个auto_ptr的潜在危险.

你可能感兴趣的:(C++)