• c++智能指针使用笔记


    1. c++智能指针中,c++的memory文件中,有auto_ptr等各种关于智能指针的东西,shared_ptr,weak_ptr在C++11中已经成为标准。


        也看了ogs的智能指针,每次引用起来比较麻烦,规则也多。方便的是自动的引用计数,可选线程安全。

       为方便 写了个公用类,如下:

    #ifndef _test_share_ptr_h__
    #define  _test_share_ptr_h__
    
    #define  null 0
    class  student
    {
    public:
    	 student();
    	 student(float score_)
    		 :scores(score_)
    	 {
    
    	 }
    	virtual ~ student();
    public:
    	char* all_class_name;
    	float	scores;
    private:
    
    };
    
     student:: student()
    {
    }
    
     student::~ student()
    {
    	if (null != all_class_name)
    	{
    		delete []all_class_name;
    		all_class_name = null;
    	}
    }
    
    #endif


    2.auto_ptr

    功能相对简单,只能负责释加入到auto_ptr中的基类,并且基类中没有单独的到堆上申请内存。

    写的两个函数测试,一个函数类:

    void mem_ptr_student_new()
    {
    	int byte_numbers = 1024;
    	for (int i = 0; i < count_times;i++)
    	{	
    		student* pri_test_stu = new student;
    		mem::auto_ptr<student> pri_student_share_ptr(pri_test_stu);
    		pri_student_share_ptr->all_class_name = new char[byte_numbers];
    		for (int j = 0; j < byte_numbers;j++)
    		{
    			pri_student_share_ptr->all_class_name[j] = j;
    		}
    		pri_student_share_ptr->scores = (float)(i + 10);
    	}	
    }
    
    
    typedef std::vector<mem::auto_ptr<student>> mem_vector_student;
    void mem_ptr_student_vector_new()
    {
    	int byte_numbers = 1024;
    	mem_vector_student pri_test_vector;
    	/*
    	mem::auto_ptr_ref<mem_vector_student> pri_auto_ref(&pri_test_vector);
    	mem::auto_ptr<mem_vector_student> pri_vector_student_share_ptr(pri_auto_ref);
    	for (int i = 0; i < count_times;i++)
    	{	
    	mem::auto_ptr<student> pri_student_share_ptr(new student);
    	pri_student_share_ptr->all_class_name = new char[byte_numbers];
    	for (int j = 0; j < byte_numbers;j++)
    	{
    	pri_student_share_ptr->all_class_name[j] = j;
    	}
    	pri_student_share_ptr->scores = (float)(i + 10);
    	pri_vector_student_share_ptr->push_back(pri_student_share_ptr);
    	}*/
    }

    结果很明显,对于这样的类,char* all_class_name 在使用中自动申请了内存,auto_ptr很明显无能为力。内存泄露明显,所以第二个函数,stl vector的使用更不用多说,

    一样不行。


    摘抄了一段auto_ptr使用说明:

    /*---------------------------mem_auto_ptr-------------------------------------*/
    /*
     若下函数,使用mem::auto_ptr时候,不会自动调用student函数的析构,造成内存泄露。
     摘抄部分说明:
    
     * 1)auto_ptr不能共享所有权,即不要让两个auto_ptr指向同一个对象。
     * 
    
     *   2)auto_ptr不能指向数组,因为auto_ptr在析构的时候只是调用delete,而数组应该要调用delete[]。
     * 
    
     *   3)auto_ptr只是一种简单的智能指针,如有特殊需求,需要使用其他智能指针,比如share_ptr。
     * 
    
     *   4)auto_ptr不能作为容器对象,STL容器中的元素经常要支持拷贝,赋值等操作,在这过程中auto_ptr会传递所有权,那么source与sink元素之间就不等价。
    */


    3.  别人写的一个share_ptr,用来测试和比较说明。

    此类功能复杂,代码相对多。不过,挺好用。

    若有问题,随时联系,可删除。

    #ifndef __smart_shared_ptr_h__
    #define __smart_shared_ptr_h__
    
    #define  null 0
    namespace smart
    {
    	class shared_ptr_reference_count
    	{
    	public:
    		shared_ptr_reference_count()
    		{
    			_reference_count = 1;
    		}
    
    		virtual ~shared_ptr_reference_count()
    		{
    		}
    		
    		void grab()
    		{
    			_reference_count++;
    		}
    		
    		size_t drop()
    		{
    			_reference_count--;
    			return _reference_count;
    		}
    
    		size_t get_reference_count()
    		{
    			return _reference_count;
    		}
    	private:
    		size_t _reference_count;
    	};
    
    	class shared_ptr_reference_destory
    	{
    	public:
    		virtual ~shared_ptr_reference_destory(){};
    	};
    
    	template<class t>
    	class smart_shared_ptr;
    
    	class smart_shared_ptr_shadow
    	{  
    	public:
    		smart_shared_ptr_shadow()
    			: _reference_instance(null)
    			, _reference_count(null)
    			, _reference_destory(null)
    		{
    		}
    
    		smart_shared_ptr_shadow(void *instance_, shared_ptr_reference_count* reference_count_,  shared_ptr_reference_destory* reference_destory_)
    			: _reference_instance(instance_)
    			, _reference_count(reference_count_)
    			, _reference_destory(reference_destory_)
    		{
    			if(_reference_count != null)
    			{
    				_reference_count->grab();
    			}
    		}
    
    		~smart_shared_ptr_shadow()
    		{
    			if(_reference_count == null)
    			{
    				return;
    			}
    
    			if(_reference_count->drop() == 0){
    				delete _reference_destory;
    				_reference_destory = null;
    
    				delete _reference_count;
    				_reference_count = null;
    			}
    		}
    
    		smart_shared_ptr_shadow(const smart_shared_ptr_shadow& right_)
    		{
    			if(right_._reference_count != null){
    				right_._reference_count->grab();
    			}
    
    			_reference_instance = right_._reference_instance;
    			_reference_count = right_._reference_count;
    			_reference_destory = right_._reference_destory;
    		}
    
    		template<class t_>
    		smart_shared_ptr<t_> to_shared_ptr()
    		{
    			return smart_shared_ptr<t_>((t_*)_reference_instance, _reference_count);
    		}
    
    		template<class t_>
    		operator smart_shared_ptr<t_>()
    		{
    			return to_shared_ptr<t_>();
    		}
    
    		smart_shared_ptr_shadow& operator = (const smart_shared_ptr_shadow& right_)
    		{
    			if(right_._reference_count != null)
    			{
    				right_._reference_count->grab();
    			}
    
    			if(_reference_count != null)
    			{
    				if(_reference_count->drop() == 0)
    				{
    					delete _reference_destory;
    					_reference_destory = null;
    
    					delete _reference_count;
    					_reference_count = null;
    				}
    			}
    
    			_reference_instance = right_._reference_instance;
    			_reference_count = right_._reference_count;
    			_reference_destory = right_._reference_destory;
    			return *this;
    		}
    
    		bool operator == (const smart_shared_ptr_shadow& right_) const
    		{
    			return (_reference_instance == right_._reference_instance);
    		}
    
    		operator bool() const
    		{
    			return _reference_count != null;
    		}
    	private:
    		void* _reference_instance;
    		shared_ptr_reference_count* _reference_count;
    		shared_ptr_reference_destory* _reference_destory;
    	};
    
    	template<class t>
    	class smart_shared_ptr
    	{ 
    		class shared_ptr_reference_destory_impl
    			: public shared_ptr_reference_destory
    		{
    		public:
    			shared_ptr_reference_destory_impl(t* reference_instance_)
    			{
    				this->_reference_instance = reference_instance_;
    			}
    
    			virtual ~shared_ptr_reference_destory_impl()
    			{
    				delete _reference_instance;
    			}
    		private:
    			t* _reference_instance;
    		};
    
    	public:
    		smart_shared_ptr()
    			: _reference_count(null)
    			, _reference_instance(null)
    		{
    
    		}
    
    		smart_shared_ptr(t* instance_)
    			: _reference_count(new shared_ptr_reference_count)
    			, _reference_instance(instance_)
    		{
    		}
    
    		smart_shared_ptr(t* instance_, shared_ptr_reference_count* reference_count_)
    			: _reference_count(reference_count_)
    			, _reference_instance(instance_)
    		{
    			if(_reference_count != null)
    			{
    				_reference_count->grab();
    			}
    		}
    
    		~smart_shared_ptr()
    		{
    			if(_reference_count == null)
    			{
    				return;
    			}
    
    			if(_reference_count->drop() == 0)
    			{
    				delete _reference_instance;
    				_reference_instance = null;
    
    				delete _reference_count;
    				_reference_count = null;
    			}
    		}
    
    		t* operator -> ()
    		{
    			return _reference_instance;
    		}
    
    		smart_shared_ptr(const smart_shared_ptr& right_)
    		{
    			if(right_._reference_count != null)
    			{
    				right_._reference_count->grab();
    			}
    
    			_reference_instance = right_._reference_instance;
    			_reference_count = right_._reference_count;
    		}
    
    		smart_shared_ptr_shadow to_shared_ptr_shadow()
    		{
    			return smart_shared_ptr_shadow(_reference_instance, _reference_count, new shared_ptr_reference_destory_impl(_reference_instance));
    		}
    
    		template<class t_>
    		smart_shared_ptr<t_> to_shared_ptr()
    		{
    			return smart_shared_ptr<t_>((t_*)_reference_instance, _reference_count);
    		}
    
    		template<class t_>
    		operator smart_shared_ptr<t_>()
    		{
    			return to_shared_ptr<t_>();
    		}
    
    
    		operator smart_shared_ptr_shadow()
    		{
    			return to_shared_ptr_shadow();
    		}
    
    		smart_shared_ptr& operator = (const smart_shared_ptr& right_)
    		{
    			if(right_._reference_count != null)
    			{
    				right_._reference_count->grab();
    			}
    
    			if(_reference_count != null)
    			{
    				if(_reference_count->drop() == 0)
    				{
    					delete _reference_instance;
    					_reference_instance = null;
    
    					delete _reference_count;
    					_reference_count = null;
    				}
    			}
    
    			_reference_instance = right_._reference_instance;
    			_reference_count = right_._reference_count;
    
    			return *this;
    		}
    
    		template<class t_> 
    		bool operator == (const smart_shared_ptr& right_) const
    		{
    			return (_reference_instance == right_.reference_instance);
    		}
    
    
    		operator bool() const
    		{
    			return _reference_count != null;
    		}
    
    		bool is_null() const
    		{
    			return _reference_count != null;
    		}
    	private:
    		shared_ptr_reference_count* _reference_count;
    		t* _reference_instance;
    	};
    	
    #endif
    


    同样的测试代码,只是里面类名称改变一下。如下:

    void smart_ptr_student_new()
    {
    	int byte_numbers = 1024;
    	for (int i = 0; i < count_times;i++)
    	{	
    		smart_shared_ptr<student> pri_student_share_ptr = new student;
    		pri_student_share_ptr->all_class_name = new char[byte_numbers];
    		for (int j = 0; j < byte_numbers;j++)
    		{
    			pri_student_share_ptr->all_class_name[j] = j;
    		}
    		pri_student_share_ptr->scores = (float)(i + 10);
    	}	
    }
    
     
    typedef std::vector<smart_shared_ptr<student>> vector_student;
    void smart_ptr_student_vector_new()
    {
    	int byte_numbers = 1024;
    	smart_shared_ptr<vector_student> pri_vector_student_share_ptr = new vector_student();
    	for (int i = 0; i < count_times;i++)
    	{	
    		smart_shared_ptr<student> pri_student_share_ptr = new student;
    		pri_student_share_ptr->all_class_name = new char[byte_numbers];
    		for (int j = 0; j < byte_numbers;j++)
    		{
    			pri_student_share_ptr->all_class_name[j] = j;
    		}
    		pri_student_share_ptr->scores = (float)(i + 10);
    		pri_vector_student_share_ptr->push_back(pri_student_share_ptr);
    	}
    }


    结果:很明显,可管理类的对象指针和vector中的对象指针,因为重载了等号,括号,实时可以记录指针的使用次数,并处理了析构。计数的做为个类来处理,比有的智能

    指针用个static的变量来好很多。

    但是各种此类型的指针可以相互赋值,因为里面用的指针一律是void* 造成的。


    3. 一个简单的ptr

    不知道是否有问题啊。目前看起来还行。

    #ifndef __m_smart_ptr_h__
    #define  __m_smart_ptr_h__
    
    #include <iostream>
    #include <stdexcept>
    using namespace std;
    
    #define test_smart_ptr_cout
    namespace s_smart
    {
    	template <typename T>
    	class simple_smart_ptr 
    	{
    	public:
    		simple_smart_ptr(T *p = 0): ptr(p), p_use_count(new size_t(1)) 
    		{
    		}
    
    		simple_smart_ptr(const simple_smart_ptr& src): ptr(src.ptr), p_use_count(src.p_use_count)
    		{
    			++*p_use_count;
    		}
    
    		simple_smart_ptr& operator= (const simple_smart_ptr& rhs) {
    			// self-assigning is also right
    			++*rhs.p_use_count;
    			decrUse();
    			ptr = rhs.ptr;
    			p_use_count = rhs.p_use_count;
    			return *this;
    		}
    
    		T *operator->() 
    		{
    			if (ptr)
    				return ptr;
    			throw std::runtime_error("access through NULL pointer");
    		}
    		const T *operator->() const 
    		{ 
    			if (ptr)
    				return ptr;
    			throw std::runtime_error("access through NULL pointer");
    		}
    
    		T &operator*() 
    		{
    			if (ptr)
    				return *ptr;
    			throw std::runtime_error("dereference of NULL pointer");
    		}
    
    		const T &operator*() const 
    		{
    			if (ptr)
    				return *ptr;
    			throw std::runtime_error("dereference of NULL pointer");
    		} 
    
    		~simple_smart_ptr() 
    		{
    			decrUse();
    #ifdef test_smart_ptr_cout
    			std::cout<<"simple_smart_ptr: Destructor"<<std::endl; // for testing
    #endif
    		}
    
    	private:
    		void decrUse() 
    		{
    			if (--*p_use_count == 0) {
    				delete ptr;
    				delete p_use_count;
    			}
    		}
    		T *ptr;
    		size_t *p_use_count;
    	};
    }
    
    #endif
    


    同样的测试过程,均可用。对类的指针有删除能力。


    以上的智能指针的操作没有线程安全。

    在osg的有一个宏定义来定义,是否启用原子操作的,_OSG_REFERENCED_USE_ATOMIC_OPERATIONS,对于计数的操作是安全的。


    完结了!

    本文代码下载地址:http://download.csdn.net/detail/cartzhang/7004199

    形式是多种的,内容是一致的。

    若有问题,请及时指正!




  • 相关阅读:
    ES6判断对象是否为空
    mui、拍照、个推推送消息【问题链接】
    查找SAP某个Tcode下已经实施的增强
    MySQL 事务
    Go 学习线路图
    Nginx 限流配置
    Redis 内存优化
    2021年 github被墙最新hosts-每日更新
    Nginx 反向代理与负载均衡详解
    完美实现跨域 iframe 高度自适应
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461986.html
Copyright © 2020-2023  润新知