首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++ shared_ptr智能指针运用注意事项

2012-09-23 
c++shared_ptr智能指针使用注意事项shared_ptr在boost中地位相当重要,其行为最接近原始指针,但又比指针更

c++ shared_ptr智能指针使用注意事项

       shared_ptr在boost中地位相当重要,其行为最接近原始指针,但又比指针更加安全,甚至还能提供基本的线程安全保证。它基本上解决了在使用c++开发过程中不可避免的使用指针而遇到的许多问题,常见的毫无疑问是内存泄漏和内存的提前释放,还有一些关于指针内存申请而产生的异常问题等。而要想较好的使用shared_ptr来完全取代指针绝非易事。下面简要说说使用shared_ptr需要注意的问题。

       1.share_ptr是一个类,它产生的是一个类对象,而不是一个原生的指针对象,但是为了减少类对象与针对对象使用的差异性,所以share_ptr类故意重载了两种常见的指针操作符: *和->。从而share_ptr与普通指针使用方式一样。简言之,就是share_ptr生成的一个包含类型指针容器对象,它封装了指针对象,对指针对象负全责,包括生成、释放等

      2.特别需要注意的是,share_ptr的转型函数不能使用c++常用的转型函数,即static_cast,dynamic_cast,const_cast,而要使用static_pointer_cast,dynamic_pointer_cast,const_pointer_cast。原因有两个:static_cast,dynamic_cast,const_cast的功能是转换成对应的模版类型,即static_cast<T*>其实是转换成类型为T的指针;前面说了share_ptr生成的一个包含类型指针容器对象,使用简单的c++转型函数是将share_ptr对象转型为模版指针对象,这完全违背了使用share_ptr的初衷(除非你确确实实有这种需要!),导致转型的模版指针对象不能采用share_ptr进行管理。因为上面的两个原因:share_ptr为了支持转型,所以提供了类似的转型函数即static_pointer_cast<T>,从而使转型后仍然为shared_pointer对象,仍然对指针进行管理;

     3.share_ptr类重载了许多的构造函数,其中包含无参的构造函数用来创建一个持有空指针的share_ptr对象,,注意它不等价于持有void*型的指针对象。要想生成一个存储void*型的指针,可以使用share_ptr(void*)构造函数来构造,它相当于一个泛型的指针容器,拥有容纳任意类型的能力,但是将包含void*指针的shared_ptr对象使用注意2中的转型函数转型为某种类型的指针会使代码不够安全,一般不要使用;

     4.share_ptr完美支持标准容器,并且不需要担心资源泄漏。而标准容易在使用指针对象时需要特别的小心,对指针需要额外的管理。下面用代码范例来演示如何将share_ptr应用与标准容器:

#include <boost/make_shared.hpp>#include <vector>using namespace std;using namespace boost;int main (int argc, const char * argv[]){    typedef vector< shared_ptr<int> > sharedContainers;    sharedContainers sharedArray(10);    int i=0;    for(sharedContainers::iterator pos = sharedArray.begin() ;pos!=sharedArray.end();++pos)     {        *pos = make_shared<int>(++i);    }    cout<<"sharedArray[5]的初始值:"<<*sharedArray[5]<<endl;    cout<<"sharedArray[5]的初始引用计数为:"<<sharedArray[5].use_count()<<endl;    shared_ptr<int> p1 = sharedArray[5];    *p1 = 10;    cout<<"sharedArray[5]经过赋值后的值:"<<*sharedArray[5]<<endl;    cout<<"sharedArray[5]赋值后的引用计数为:"<<sharedArray[5].use_count()<<endl;    shared_ptr<int> p2(sharedArray[5]);    cout<<"sharedArray[5]复制和赋值后的引用计数为:"<<sharedArray[5].use_count()<<endl;    cout<<"sharedArray[5]的地址:"<<sharedArray[5]<<",p1的地址:"<<p1<<",p2的地址:"<<p2<<endl;    *p2 = 5;    cout<<"sharedArray[5]经过复制后的值:"<<*sharedArray[5]<<endl;    return 0;    }

其输出结果为:

sharedArray[5]的初始值:6
sharedArray[5]的初始引用计数为:1
sharedArray[5]经过赋值后的值:10
sharedArray[5]赋值后的引用计数为:2
sharedArray[5]复制和赋值后的引用计数为:3
sharedArray[5]的地址:0x10010092c,p1的地址:0x10010092c,p2的地址:0x10010092c
sharedArray[5]经过复制后的值:5

可以看到,经过赋值和复制后的sharedArray[5],其引用计数增1。而且经过赋值和复制后的sharedArray[5]对象p1和p2所指向的地址完全相同。所以随便改变其中之一的值,另外两个对象指向的值也随之改变,这也是共享资源的精髓吧!

      6. share_ptr针对封装的指针要求,可以定制删除器,即使用构造函数shared_ptr(Y *p , D d)来构造shared_ptr指针。其中第一个参数是要被管理的指针,其含义与其他构造函数一样。而第二个参数,即删除器参数d则告诉shared_ptr在析构时不是使用普通的delete方法来析构指针p,而是用方法d来操作,即用d(p)来代替delete p。这里的d只需要能够像函数一样被调用,所以d既可以是一个函数对象,也可以是一个函数指针。这种删除器d比较适用于指针对象p在删除时有一定的要求,例如某中类指针,有专门的析构函数,但切记d的实参对象行为必须与delete一样,不能抛出异常,并且是可拷贝的。

      上面说了这么多,其实这只是shared_ptr的一小部分,还有很多涉及c++哲学方面的问题需要注意,例如延时释放、包装成员函数等。

      本文如有错误,欢迎指正,对此十分感谢!


热点排行