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
形式是多种的,内容是一致的。
若有问题,请及时指正!