Chinaunix首页 | 论坛 | 博客
  • 博客访问: 581045
  • 博文数量: 104
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1559
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-21 00:58
个人简介

锻炼精神,首先要锻炼肉体

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: C/C++

2015-05-11 15:24:06

1.shared_ptr  和 scoped_ptr 的不同之处

1.1.shared_ptr 是允许转让的,而 scoped_ptr 是不允许权限转让的,转让的代码实现和定义在后面几段中有详细介绍,
不过简单的说就是 
scoped_ptr 不支持同时创建两个指向相同类型的 scoped_ptr 指针让他们指向同一个对象实例

1.2.shared_ptr 可以作为标准容器的元素,而 scoped_ptr 是不可以的

1.3. shared_ptr 支持空指针的创建(常用于查找对象指针的时候,如果查找不到返回空指针的情况,因为在这种情况下不能够简单的返回 NULL ),而scoped_ptr 却不支持空指针

1.4. shared_ptr 支持引用计数,只有它支持引用计数,所谓的引用计数就是指:
创建一个对象 T , 然后创建多个指向该对象的 shared_ptr n1...nx ;  每个指针 n* 通过调用 n*.use_count () 方法的返回值(int)便可以获知,
当前除了自己以外是否还有
其它的shared_ptr 指针指向该对象实例 T。返回值(int) 便可以称作是该对象 T 的引用计数。
只有当引用计数的数值为 0 的时候,调用 shared_ptr.reset() 方法才会将该对象 T 的空间进行释放,
否则仅仅是当前调用 reset() 方法的shared_ptr
指针所指向的引用计数数值 -1 ,并断开指针和对象之间的关联。



做实验的时候,很多代码都是在前面的基础之上进行修改的,多少有一些重复的地方

2. scoped_ptr 和 shared_ptr 的模板定义方法
2.1. boost::scoped_ptr

点击(此处)折叠或打开

  1. namespace boost {

  2.     template<typename T> class scoped_ptr : noncopyable {
  3.     public:
  4.         explicit scoped_ptr(T* p = 0);
  5.         ~scoped_ptr();

  6.         void reset(T* p = 0);

  7.         T& operator*() const;
  8.         T* operator->() const;
  9.         T* get() const;

  10.         void swap(scoped_ptr& b);
  11.     };

  12.     template<typename T>
  13.     void swap(scoped_ptr<T> & a, scoped_ptr<T> & b);
  14. }
2.2. boost::shared_ptr 

点击(此处)折叠或打开

  1. template <typename T>
  2. class shared_ptr
  3. {
  4.   public :
  5.     typedef T element_type ;
  6.     
  7.     shared_ptr () ;
  8.     template<typename Y >
  9.     explicit shared_ptr ( Y *p ) ;
  10.     
  11.     template <typename Y , typename D>
  12.     shared_ptr ( Y*p , D d ) ;
  13.     
  14.     ~shared_ptr () ;
  15.     
  16.      shared_ptr (shared_ptr const & r ) ;
  17.     
  18.     template <typename Y>
  19.     explicit shared_ptr ( std::auto_ptr <Y> & r ) ;
  20.     
  21.     shared_ptr & operator=(shared_ptr const &r ) ;
  22.     
  23.     template <typename Y>
  24.     shared_ptr &operator= (shared_ptr<Y> const &r ) ;
  25.     
  26.     template <typename Y>
  27.     shared_ptr &operator=(std::auto_ptr<Y> &r ) ;
  28.     
  29.     void reset () ;
  30.     
  31.     template <typename Y>
  32.     void reset ( Y* p ) ;
  33.     
  34.     template <typename Y, typename D>
  35.     void reset ( Y*p , D d ) ;
  36.     
  37.     T & operator*() const ;
  38.     T * operator->() const ;
  39.     T * get () const ;
  40.     
  41.     
  42.     bool unique () const ;
  43.     long use_count () const ;
  44.     
  45.     operator unspecified-bool-type () const ;
  46.     void swap( shared_ptr & b ) ;
  47. } ;




3. 代码实例转让的含义
   

点击(此处)折叠或打开

  1. #include <boost/shared_ptr.hpp>
  2. #include <boost/scoped_ptr.hpp>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <iostream>

  6. /**
  7. this file is used to justify the difference between boost::scoped_ptr and boost::shared_ptr
  8. results:
  9. 1. shared_ptr can hands in its possion on an object , however the scoped_ptr doesn't
  10. 2. when you write something to let scoped_ptr hands in its possion on some object
  11.     spaces allocated to that object will be released immediately
  12.     but , unfortunately the output contents won't be shown on the screen cause the error message
  13.     
  14.     by Aimer
  15. */



  16. template <typename T>
  17. class sharedPtr
  18. {
  19.     public :
  20.     typedef boost::shared_ptr<T> type ;
  21. } ;

  22. template <typename T>
  23. class scopedPtr
  24. {
  25.     public :
  26.     typedef boost::scoped_ptr<T> type ;
  27. } ;

  28. class obj
  29. {
  30.     public :
  31.       obj ( std::string& n )
  32.      {
  33.          name = n ;
  34.          std::cout << "you get a obj " << name << std::endl ;
  35.      }
  36.      
  37.      void print ()
  38.      {
  39.          std::cout << "the programmer loves " <<name << std::endl ;
  40.      }
  41.      
  42.      ~obj ()
  43.      {
  44.         std::cout << "good bye " << name << std::endl;
  45.      }
  46.      
  47.      private :
  48.      std::string name ;
  49. } ;


  50. int main ( void )
  51. {
  52.     std::string name ("kylin_zhang") ;
  53.     
  54.     // first we test whether shared_ptr can transfer the possion of a obj instance
  55.     sharedPtr<obj>::type p1 (new obj(name)) ;
  56.     sharedPtr<obj>::type p2 = p1 ;
  57.     
  58.     p2->print () ;
  59.     
  60.     
  61.     // then we test whether the scoped_ptr can hand in its possion of a obj
  62.     std::string name_ ("singer aimer") ;
  63.     scopedPtr<obj>::type q1 (new obj(name_)) ;
  64.     
  65.     
  66.  /*
  67.     remove the notes , if you want to check the error message
  68.     scopedPtr<obj>::type q2  =  q1 ;
  69. */
  70.     std::cout << std::endl ;
  71.     
  72.     std::cout << "here we will transfer the posssion from q1 to q2" <<std::endl;
  73.     scopedPtr<obj>::type q2 ;
  74.     q1.swap (q2) ;
  75.     // after this q1's object is handed to q2 , so , q1->print() will prompt error message
  76.     
  77.     
  78.     q2->print () ;
  79.     
  80.     
  81.    // q1->print () ; this will cause error , cause the space could only be visited by q2 itself
  82.    
  83.    
  84.    // here we test whether the scoped_ptr can use scopedPtr<T>::type () ; to create an empty scoped pointer
  85.   // scopedPtr<obj>::type empty = scopedPtr<obj>::type() ;
  86.    
  87.    sharedPtr<obj>::type spEmpty = sharedPtr<obj>::type() ;
  88.    
  89.     
  90.     std::cout << "end of file pointers release their objects' space" <<std::endl ;
  91.     
  92.     return 0 ;
  93. }



4. boost 中的 explicit/noncopyable 来实现 scoped_ptr 的
禁止转让功能 ,   scoped_ptr 通过swap 来实现一定程度的转让功能
 

点击(此处)折叠或打开

  1. #include <boost/shared_ptr.hpp>
  2. #include <boost/scoped_ptr.hpp>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <iostream>

  6. /**
  7. this file is used to justify the difference between boost::scoped_ptr and boost::shared_ptr
  8. results:
  9. 1. shared_ptr can hands in its possion on an object , however the scoped_ptr doesn't
  10. 2. when you write something to let scoped_ptr hands in its possion on some object
  11.     spaces allocated to that object will be released immediately
  12.     but , unfortunately the output contents won't be shown on the screen cause the error message
  13.     
  14.     by Aimer
  15. */



  16. template <typename T>
  17. class sharedPtr
  18. {
  19.     public :
  20.     typedef boost::shared_ptr<T> type ;
  21. } ;

  22. template <typename T>
  23. class scopedPtr
  24. {
  25.     public :
  26.     typedef boost::scoped_ptr<T> type ;
  27. } ;

  28. class obj
  29. {
  30.     public :
  31.       obj ( std::string& n )
  32.      {
  33.          name = n ;
  34.          std::cout << "you get a obj " << name << std::endl ;
  35.      }
  36.      
  37.      void print ()
  38.      {
  39.          std::cout << "the programmer loves " <<name << std::endl ;
  40.      }
  41.      
  42.      ~obj ()
  43.      {
  44.         std::cout << "good bye " << name << std::endl;
  45.      }
  46.      
  47.      private :
  48.      std::string name ;
  49. } ;


  50. int main ( void )
  51. {
  52.     std::string name ("kylin_zhang") ;
  53.     
  54.     // first we test whether shared_ptr can transfer the possion of a obj instance
  55.     sharedPtr<obj>::type p1 (new obj(name)) ;
  56.     sharedPtr<obj>::type p2 = p1 ;
  57.     
  58.     p2->print () ;
  59.     
  60.     
  61.     // then we test whether the scoped_ptr can hand in its possion of a obj
  62.     std::string name_ ("singer aimer") ;
  63.     scopedPtr<obj>::type q1 (new obj(name_)) ;
  64.     
  65.     
  66.  /*
  67.     remove the notes , if you want to check the error message
  68. */
  69.     std::cout << std::endl ;
  70.     
  71.     std::cout << "here we will transfer the posssion from q1 to q2" <<std::endl;
  72.     scopedPtr<obj>::type q2 ;
  73.     q1.swap (q2) ;
  74.     // after this q1's object is handed to q2 , so , q1->print() will prompt error message
  75.     
  76.     
  77.     q2->print () ;
  78.     
  79.     
  80.    // q1->print () ; this will cause error , cause the space could only be visited by q2 itself
  81.     
  82.     std::cout << "end of file pointers release their objects' space" <<std::endl ;
  83.     
  84.     return 0 ;
  85. }

点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstdlib>

  4. /**
  5.  this test is used to testify how does explicit works on class ' s constructors

  6.  by Aimer 5/11/2015
  7. **/

  8. class obj1
  9. {
  10. public :
  11.    explicit obj1 ( const obj1 & o )
  12.    {
  13.        name = o.name ;
  14.    }
  15.    
  16.    explicit obj1 ( std::string& n )
  17.     {
  18.         name = n ;
  19.     }
  20.     void print ()
  21.     {
  22.         std::cout << " my name is obj1's " << name << std::endl ;
  23.     }
  24. public :
  25.     std::string name ;

  26. } ;

  27. class obj2
  28. {
  29. public :
  30.     obj2( const obj2 &o)
  31.     {
  32.         name = o.name+" copyed " ;
  33.     }
  34.     
  35.     obj2( std::string & n )
  36.     {
  37.         name = n;
  38.     }
  39.     
  40.     void print ()
  41.     {
  42.         std::cout << "my name is obj2's " << name << std::endl ;
  43.     }
  44.     
  45.     private :
  46.     std::string name ;

  47. } ;


  48. int main ( )
  49. {
  50.     std::string name ("kylin") ;
  51.     
  52. std::cout << "ok here we test the explicit obj1's string and non-explicit obj2's string constructor " << std::endl ;
  53.     
  54.     
  55.     /*
  56.     this will arise error , cause the explicit of string parameter constructor
  57.     obj1 obj1_1 = name ;
  58.     obj1_1.print() ;
  59.     */
  60.     
  61.     // this will be ok
  62.     obj2 obj2_1 = name ;
  63.     obj2_1.print () ;
  64.     
  65. std::cout << "---------------------------------------------------------------------------------------------"<<std::endl ;
  66. std::cout << "ok here we test the explicit obj1's string and non-explicit obj2's object & constructors " << std::endl ;
  67.     
  68.     /**
  69.        right ! , following codes will arise error again , because of the explicit again
  70.        
  71.        obj1 obj1_2 = obj1_1 ;
  72.        obj1_2.print () ;
  73.     */
  74.     
  75.     
  76.     obj2 obj2_2 = obj2_1 ;
  77.     obj2_2.print () ;
  78.     
  79.     
  80.     return 0 ;
  81.     
  82. }


点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstdlib>

  4. /**
  5.  this test is used to testify how does explicit works on class ' s constructors

  6.  by Aimer 5/11/2015
  7. **/

  8. class obj1
  9. {
  10. public :
  11.    explicit obj1 ( const obj1 & o )
  12.    {
  13.        name = o.name+" copyed " ;
  14.    }
  15.    
  16.    explicit obj1 ( std::string& n )
  17.     {
  18.         name = n ;
  19.     }
  20.     void print ()
  21.     {
  22.         std::cout << " my name is obj1's " << name << std::endl ;
  23.     }
  24. public :
  25.     std::string name ;

  26. } ;

  27. class obj2
  28. {
  29. public :
  30.     obj2( const obj2 &o)
  31.     {
  32.         name = o.name+" copyed " ;
  33.     }
  34.     
  35.     obj2( std::string & n )
  36.     {
  37.         name = n;
  38.     }
  39.     
  40.     void print ()
  41.     {
  42.         std::cout << "my name is obj2's " << name << std::endl ;
  43.     }
  44.     
  45.     private :
  46.     std::string name ;

  47. } ;


  48. int main ( )
  49. {
  50.     std::string name ("kylin") ;
  51.     
  52. std::cout << "ok here we test the explicit obj1's string and non-explicit obj2's string constructor " << std::endl ;
  53.     
  54.     
  55.     /*
  56.     this will arise error , cause the explicit of string parameter constructor
  57.     obj1 obj1_1 = name ;
  58.     obj1_1.print() ;
  59.     */
  60.     
  61.     // this will be ok
  62.     obj2 obj2_1 = name ;
  63.     obj2_1.print () ;
  64.     
  65. std::cout << "---------------------------------------------------------------------------------------------"<<std::endl ;
  66. std::cout << "ok here we test the explicit obj1's string and non-explicit obj2's object & constructors " << std::endl ;
  67.     
  68.     /**
  69.        right ! , following codes will arise error again , because of the explicit
  70.        
  71.        obj1 obj1_2 = obj1_1 ;
  72.        obj1_2.print () ;
  73.     */
  74.     obj1 obj(name) ; // here we creates an obj1 's instance in right rules
  75.     obj.print () ; // if this work , it means every goes well in obj
  76.     
  77.     obj1 obj1_3 (obj) ; // this line goes all right , cause explicit could not detect this , you can use noncopyable from boost
  78.                         // to ban this , may be that's why we will use boost::noncopyable
  79.     obj1_3.print () ;
  80.     
  81.     obj2 obj2_2 = obj2_1 ;
  82.     obj2_2.print () ;
  83.     
  84.     
  85.     return 0 ;
  86.     
  87. }



5. shared_ptr和scoped_ptr 的声明与使用方法
    

点击(此处)折叠或打开

  1. /**
  2. in this test , i will show you how to packed scoped_ptr and shared_ptr by template meta-function and
  3. how to create an instance (both struct and class) by scoped_ptr

  4. by Aimer

  5. 2015/5/11
  6. */

  7. #include <cstdio>
  8. #include <string>
  9. #include <iostream>
  10. #include <cassert>

  11. #include <boost/scoped_ptr.hpp>
  12. #include <boost/shared_ptr.hpp>

  13. template <typename T>
  14. class scopedPtr
  15. {
  16. public :
  17.    typedef boost::scoped_ptr<T> type ;
  18. } ;


  19. template <typename T>
  20. class sharedPtr
  21. {
  22. public :
  23.    typedef boost::shared_ptr<T> type ;
  24. } ;


  25. typedef struct node
  26. {
  27.     node () : file_name(NULL) , fp(NULL)
  28.     {}
  29.     node ( std::string &path ) : file_name ( path )
  30.     {
  31.         fp = fopen (path.c_str() , "r") ;
  32.         
  33.        // assert ( fp ) ;
  34.     }
  35.     
  36.     ~node ()
  37.     {
  38.         std::cout << "release node_t " << file_name << std::endl ;
  39.     }
  40.     
  41.     void print ()
  42.        {
  43.            std::cout << "node open " << file_name << std::endl ;
  44.        }

  45.     std::string file_name ;
  46.     FILE* fp ;
  47.     
  48. }node_t ;

  49. class FileManager
  50. {
  51.     public :
  52.        FileManager () : file_name ( NULL ) , fp( NULL )
  53.        {}
  54.        FileManager ( std::string &name )
  55.        {
  56.           file_name = name ;
  57.           
  58.           fp = fopen ( file_name.c_str() , "r" ) ;
  59.           
  60.           //assert (fp) ;
  61.        }
  62.        
  63.        ~FileManager ()
  64.        {
  65.          std::cout << "release FileManager " << file_name << std::endl ;
  66.        }
  67.        
  68.        void print ()
  69.        {
  70.            std::cout << "FileManager open " << file_name << std::endl ;
  71.        }
  72.     private :
  73.      std::string file_name ;
  74.      FILE *fp ;
  75. } ;


  76. int main ()
  77. {
  78.     std::string name = "aimer.txt" ;
  79.    /*
  80.     FileManager *pFileManger = new FileManager( name ) ;
  81.     node_t* pNode = new node_t (name ) ;
  82.     */

  83. // here is how to create an instance (class/struct type) by boost::scoped_ptr by its constructor
  84.     std::cout << "============================ scoped_ptr tests = =======================================" << std::endl ;
  85.     scopedPtr<FileManager>::type pFileManager ( new FileManager( name ) ) ;
  86.     scopedPtr<node_t>::type pNode ( new node_t(name) ) ;
  87.     
  88.     scopedPtr<FileManager>::type pFileManager1 ;
  89.     scopedPtr<node_t>::type pNode1 ;
  90.     
  91. // here is another way to create an instance (class/struct type) by boost::scoped_ptr by its constructor
  92. // it works well on shared_ptr but doesn't work well on scoped_ptr
  93. // std::string name_ = "kokia.txt" ;
  94.     
  95. // pFileManager1 = scopedPtr<FileManager> ( new FileManager (name_) ) ;
  96. // pNode1 = scopedPtr<node_t>::type ( new node_t (name_)) ;


  97. // here is how to use boost::scoped_ptr to call the instance's function
  98.     
  99.     pFileManager->print () ;
  100.     
  101.     pNode->print () ;
  102.     
  103.     std::cout << "=================  shared_ptr tests ===========================" << std::endl ;
  104.     
  105.     std::string name1 ("shared_ptr ---> kylin_zhang ") ;
  106.     sharedPtr<FileManager>::type spFileManager( new FileManager(name1)) ;
  107.     sharedPtr<node_t>::type spNode ( new node_t( name1 ) ) ;

  108.     spFileManager->print() ;
  109.     spNode->print () ;
  110.     
  111.     // here we will test another way to create instances (class / struct ) by shared ptr
  112.     
  113.     sharedPtr<FileManager>::type spFileManager1 ;
  114.     sharedPtr<node_t>::type spNode1 ;
  115.     
  116.     std::string name2("shared_ptr ----> naruto ") ;
  117.     
  118.     spFileManager1 = sharedPtr<FileManager>::type ( new FileManager ( name2)) ;
  119.     spFileManager1->print () ;
  120.     
  121.     spNode1 = sharedPtr<node_t>::type ( new node_t ( name2) ) ;
  122.     spNode1->print () ;
  123.     
  124.     /*
  125.     here we got another conclusion :
  126.     boost::shared_ptr support the second way to create an instance (struct/class)
  127.     but the boost::scoped_ptr not
  128.     
  129.     it must have soemthing to do with the authority transfer of scoped_ptr
  130.     */
  131.     
  132.     
  133.     std::cout << "============== === destructor call  == ==========================" << std::endl ;
  134.     std::cout << " next you will see , before the end of the program scoped_ptr will call the 
  135.                     corresponding destruct methods" <<std::endl ;
  136.     
  137.     
  138.     return 0 ;
  139. }
  


6.关于 shared_ptr 中的引用计数的使用实例
 
 

点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <iostream>

  3. #include <boost/shared_ptr.hpp>

  4. template <typename T>
  5. class sharedPtr
  6. {
  7.     public :
  8.      typedef boost::shared_ptr<T> type ;
  9. } ;

  10. typedef struct node
  11. {
  12.     std::string name ;
  13.     node () : name(NULL)
  14.     {}
  15.     node ( std::string &n ) : name (n )
  16.     {}
  17.     
  18.     ~node ()
  19.     {
  20.         std::cout << "release node " << name << std::endl ;
  21.     }
  22.         
  23.     void print ()
  24.     {
  25.         std::cout << "node name " << name << std::endl;
  26.     }
  27.     
  28. } node_t ;


  29. template <typename T>
  30. class shared_node
  31. {
  32. public :
  33.     shared_node ( typename sharedPtr<T>::type& n ) :node ( n )
  34.     {
  35.          // n->print () ;
  36.         
  37.     }
  38.   /*
  39.     this constructor will not change the counter , because , it re-new an object
  40.     instead of create a pointer lets multi-pointers point to a same object's space
  41.     
  42.     shared_node ( typename sharedPtr<T>::type n ) : node ( new T( *n) )
  43.     {
  44.       // node = typename sharedPtr<T>::type ( new T(*n) ) ; // counter == 1
  45.     }
  46. */
  47.     void print ()
  48.     {
  49.         std::cout<< "reference counter : " << node.use_count() << std::endl ;
  50.         node->print () ;
  51.     }
  52. private :
  53.     typename sharedPtr<T>::type node ;
  54. } ;


  55. template <typename T>
  56. void print_func ( typename sharedPtr<T>::type n)
  57. {
  58.     std::cout << "reference counter :" << n.use_count() << std::endl ;
  59.     n->print () ;
  60. }

  61. int main ()
  62. {
  63.     std::string name ("kylin_zhang") ;
  64.     
  65.     std::cout << "================= print_func shows=======================" <<std::endl ;
  66.     
  67.     sharedPtr<node_t>::type p ( new node_t (name) ) ; // use counter = 1
  68.     
  69.     print_func<node_t>(p) ; // use counter = 2 , after get out of method , counter = 1
  70.     
  71.     std::cout << "================= shared_node print shows=======================" <<std::endl ;
  72.     
  73.  // sharedPtr<shared_node<node_t> >::type s1(p) , s2(p) ;
  74.     
  75.    shared_node<node_t> s1(p) , s2(p) ;

  76.    std::cout << "p 's use counter " << p.use_count () << std::endl; // p's counter = 3
  77.    
  78.    s1.print () ; // counter =1
  79.   
  80.    s2.print () ; // s2's p's counter =1
  81.    
  82.    
  83.    while ( p.use_count() != 0 )
  84.     {
  85.         std::cout << "use counter " << p.use_count() << std::endl ;
  86.         p.reset() ;
  87.         
  88.         // theory until p's use_counter == 0 , will p call delete method to release the space , if use_counter != 0 only executing use_counter-- operation
  89.         // but , in practice , p.reset() once , p.use_count() == 0 , what this hell ? i do not clear
  90.     }
  91.     std::cout << "================= destructor shows=======================" <<std::endl ;
  92.     return 0 ;
  93. }
end


on line codes reference :

转让 


转让 adds swap 


adds explicity but without noncopyable 


adds other detail 


usage of scoped_ptr and shared_ptr


final usage of scoped_ptr and shared_ptr :


something about reference counter of shared_ptr 
阅读(3915) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~