首页 > 代码库 > boost之智能指针
boost之智能指针
内存管理一直是令C++程序员最头疼的工作,C++继承了C那高效而又灵活的指针,使用起来稍微不小心就会导致内存泄露、野指针、越界访问等访问。虽然C++标准提供了只能指针std::auto_ptr,但是并没有解决所有问题。boost的smart_ptr库是对C++98标准的绝佳补充。它提供了六种智能指针,包括scoped_ptr、scoped_array、shared_ptr、shared_array、week_ptr、instrusive_ptr(不建议使用)。现在我们就学习一下这几种智能指针的使用方法和注意事项:
#include<boost/smart_ptr.hpp>#include<boost/smart_ptr/scoped_ptr.hpp>#include<boost/make_shared.hpp>#include<boost/enable_shared_from_this.hpp>#include<string>#include<vector>#include<cstdio>using namespace std;using namespace boost;struct posix_file{ posix_file(const char* file_name) { cout<<"open file:"<<file_name<<endl; } ~posix_file() { cout<<"close file"<<endl; }};void any_func(void* p){ cout<<"some operate"<<endl;}class self_shared : public enable_shared_from_this<self_shared>{public: self_shared(int n):x(n){} int x; void print() { cout<<"self_shared:"<<x<<endl; }};void ptr_test(){ /*scoped_ptr*/ scoped_ptr<string> sp(new string("text")); cout<<*sp<<endl; cout<<sp->size()<<endl; //delete sp; 不需要delete //scoped_ptr<string> sp1(sp); 不允许,拷贝构造函数为私有 //scoped_ptr<string> sp2 = sp; 不允许,赋值函数为私有 //sp++; //错误,未定义++操作 scoped_ptr<int> p(new int); if(p) //在bool语境中测试指针是否有效 { *p=100; //可以向普通指针一样使用解引用操作符* cout<<*p<<endl; } p.reset(); //reset()置空scoped_ptr if(p==0) { cout<<"该指针为空"<<endl; } if(!p) //在bool语境中测试,可以用!操作符 { cout<<"该指针为空"<<endl; } //将在离开作用域是自动析构,从而关闭文件释放资源 scoped_ptr<posix_file> fp(new posix_file("a.txt")); /*auto_ptr 和 scoped_ptr 区别*/ auto_ptr<int> ap(new int(10)); //一个int的自动指针 scoped_ptr<int> sp3(ap); //从 auto_ptr 获得原始指针 if(ap.get()==0) //原auto_ptr不再拥有指针 { cout<<"该指针为空"<<endl; } ap.reset(new int(20)); //auto_ptr 拥有新的指针 cout<<*ap<<","<<*sp3<<endl; auto_ptr<int> ap2; ap2 = ap; //ap2从ap获得原始指针,发生所有权转移 if(ap.get()==0) cout<<"该指针为空"<<endl; //ap不再拥有指针 scoped_ptr<int> sp2; //sp2 = sp; //赋值操作,无法编译通过 /*scoped_array*/ /*构造函数接受的指针p必须是new[]的结果,而不是new表达式的结果;*/ /*没有*和->操作符重载,因为scoped_array持有的不是一个普通的指针*/ /*析构函数使用delete[]释放资源,而不是delete*/ /*提供operator[]操作符重载,可以向普通数组一样用下标访问元素*/ /*没用begin()和end()等类似容器的迭代器操作函数*/ /*不能拷贝不能赋值*/ scoped_array<int> sa(new int[100]); //包装动态数组 sa[0] = 10; /*调用[]重载函数 scoped_array 不提供数组索引的范围检查*/ //*(sa+1) = 20; 错误用法 int* arr = new int[100]; //一个整数的动态数组 scoped_array<int> sa1(arr); //scoped_array 对象代理原始动态数组 fill_n(&sa1[0],100,5); //可以使用标准库算法赋值数据 sa1[10] = sa1[20] + sa1[30]; //使用起来像普通数组 /*不建议使用scoped_array*/ /*shared_ptr*/ /*shared_ptr是一个最像指针的“智能指针”,是boost.smart_ptr库中最有价值,最重要的组成部分*/ /*shared_ptr与scoped_ptr一样包装了new操作符在堆上分配的动态对象,它实现的是引用计数型的智能指针,可以自由的拷贝和赋值,可以安全的放在标准容器中*/ shared_ptr<int> spi(new int); //一个int的shared_ptr if(!spi) cout<<"该指针为空"<<endl; //在bool语境中隐式转换为bool值 *spi=253; //使用解引用操作符* shared_ptr<string> sps(new string("smart")); cout<<"该字符串长度:"<<sps->size()<<endl; //使用箭头操作符-> shared_ptr<int> spi1(new int(10)); if(spi1.unique()) cout<<"是该指针的唯一持有者"<<endl; shared_ptr<int> spi2 = spi1; //调用拷贝构造函数 //两个shared_ptr相等,指向同一个对象,引用计数为2 cout<<"spi1:"<<spi1.use_count()<<",spi2:"<<spi2.use_count()<<endl; shared_ptr<int> spi3 = spi2; cout<<"spi1:"<<spi1.use_count()<<",spi2:"<<spi2.use_count()<<",spi3:"<<spi3.use_count()<<endl; *spi3=100; cout<<"*spi1="<<*spi1<<",*spi2="<<*spi2<<"*spi3="<<*spi3<<endl; spi3.reset(); //停止shared_ptr的使用 cout<<"spi1:"<<spi1.use_count()<<",spi2:"<<spi2.use_count()<<",spi3:"<<spi3.use_count()<<endl; if(!spi3) cout<<"该指针为空"<<endl; /*shared_ptr工厂方法*/ shared_ptr<string> sps1 = make_shared<string>("make_shared"); shared_ptr<vector<int> > spv = make_shared<vector<int> >(10,2); cout<<"spv的大小:"<<spv->size()<<endl; cout<<(*spv)[0]<<endl; /*shared_ptr应用与标准容器*/ typedef vector<shared_ptr<int> > vs; vs v(10); int i=0; for(vs::iterator pos = v.begin();pos!=v.end();++pos) { (*pos) = make_shared<int> (++i); cout<<**pos<<endl; //此处两次解引用,先获得shared_ptr,在获得其内的值 } shared_ptr<int> pp = v[9]; *pp = 100; cout<<*v[9]<<endl; shared_ptr<FILE> fp1(fopen("./1.txt","r"),fclose); //带有删除器的shared_ptr,析构的时候调用fclose关闭内部的指针 /*shared_ptr<void>*/ shared_ptr<void> vp((void*)0,any_func); //容纳空指针,定制删除器 /*shared_array*/ /*shared_array构造函数接受的指针p必须是new[]的结果,而不能是new表达式的结果*/ /*shared_array提供operator[]操作符重载,可以像普通数组一样访问元素*/ /*没有*和->操作符重载,因为shared_array持有的不是一个普通指针*/ /*析构函数使用delete[]释放资源,而不是delete*/ int* ip = new int[100]; shared_array<int> sar(ip); shared_array<int> sar1 = sar; sar[0]=10; //shared_array不提供数组索引的范围检查 cout<<"sa[0]="<<sar[0]<<",sar1[0]="<<sar1[0]<<endl; /*shared_array可以用shared_ptr<std::vector>或者std::vector<shared_ptr>来代替*/ /*week_ptr*/ /*weak_ptr是配合shared_ptr而引入的一种智能指针,没有重载operator*和->*/ /*weak_ptr充当一个观察者,观察指针的引用计数*/ shared_ptr<int> spp(new int(10)); cout<<"该指针的引用计数:"<<spp.use_count()<<endl; weak_ptr<int> wp(spp); //从shared_ptr创建weak_ptr cout<<"该指针的引用计数:"<<wp.use_count()<<endl; if(!wp.expired()) //判断week_ptr观察的对象是否失效 { shared_ptr<int> spp1 = wp.lock(); //获得一个shared_ptr *spp1 = 100; cout<<"该指针的引用计数:"<<wp.use_count()<<endl; } cout<<"该指针的引用计数:"<<wp.use_count()<<endl; wp.reset(); //if(!wp) cout<<"该指针无效"<<endl; 没有重载!操作符 if(wp.expired()) cout<<"该指针无效"<<endl; if(!wp.lock()) cout<<"获取指针失败"<<endl; /*week_ptr的的一个重要用途就是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己*/ shared_ptr<self_shared> ssp = make_shared<self_shared>(314); ssp->print(); shared_ptr<self_shared> ssp1 = ssp->shared_from_this(); ssp1->x=1000; ssp1->print(); //警告:不能从一个普通的对象(非shared_ptr)使用shared_from_this()获取shared_ptr,例如: //self_shared ss; //shared_ptr<self_shared> ssp3 = ss.shared_from_this(); /*以上语法上没问题,可以编译通过,但在运行时导致shared_ptr析构时企图删除一个栈上分配的对象,发生未定义行为*/}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。