shared_ptr的使用和陷阱
来源:互联网 发布:网络设备监控软件orion 编辑:程序博客网 时间:2024/06/10 18:06
shared_ptr的使用
分配内存
- make_shared
//make_shared<int>分配一块int类型大小的内存,并值初始化为100//返回值是shared_ptr类型,因此可以直接赋值给spshared_ptr<int> sp = make_shared<int>(100);
new
接受指针参数的只能指针构造函数是explicit的,因此,我们不能将一个内置指针隐式转化为一个只能指针,必须使用直接初始化形式
//错误! 不会进行隐式转换,类型不符合shared_ptr<int> sp1 = new int(100);//正确,直接初始化调用构造函数shared_ptr<int> sp2(new int(100000));
shared_ptr的操作
分配好了内存空间,我们就可以使用shared_ptr定义的操作了
p.get()
返回p保存的指针swap(p,q)
交换p、q中保存的指针shared_ptr<T> p(q)
p是q的拷贝,它们指向同一块内存,互相关联p = q
用q为p赋值,之后p、q指向同一块内存,q引用计数+1,p(原来内存空间的)引用计数-1p.use_count()
返回与p共享对象的智能指针数量shared_ptr<T> p(q,d)
q是一个可以转换为T*的指针,d是一个可调用对象(作为删除器),p接管q所指对象的所有权,用删除器d代替delete释放内存p.reset()
将p重置为空指针p.reset(p)
将p重置为p(的值)p.reset(p,d)
将p重置为p(的值)并使用d作为删除器
shared_ptr 关联与独立
多个共享指针指向同一个空间,它们的关系可能是关联(我们所期望的正常关系)或是独立的(一种错误状态)
shared_ptr<int> sp1(new int(10)); shared_ptr<int> sp2(sp1), sp3; sp3 = sp1; //一个典型的错误用法 shared_ptr<int> sp4(sp1.get()); cout << sp1.use_count() << " " << sp2.use_count() << " " << sp3.use_count() << " " << sp4.use_count() << endl; //输出 3 3 3 1
sp1,sp2,sp3是相互关联的共享指针,共同控制所指内存的生存期,sp4虽然指向同样的内存,却是与sp1,sp2,sp3独立的,sp4按自己的引用计数来关联内存的释放。
只有用一个shared_ptr为另一个shared_ptr赋值时,才将这连个共享指针关联起来,直接使用地址值会导致各个shared_ptr独立。
向shared_ptr传递删除器
有时候我们需要用智能指针管理非new的对象,或者是没有析构函数的类,由于shared_ptr默认使用delete来释放内存并执行析构函数,对于以上的两种情况是不适用的,所以我们要传递特别的删除器
删除器必须接受单个类型为 T* 的参数
//没有析构函数的类struct MyStruct{ int *p; MyStruct():p(new int(10)) { } //构造函数中申请了一块内存 //用裸指针管理,不用时需要手动释放};void main(){ //st是局部的对象,存放在栈区 //并非由new申请,不可用delete释放内存 MyStruct st; //一个作用域 { shared_ptr<MyStruct> sp(&st, [](MyStruct *ptr) { delete(ptr->p); ptr->p = nullptr; cout << "destructed." << endl; }); } // 离开作用域,调用传递的删除器释放sp所指的内存空间}
对于以上这个例子,首先不可以用delete来释放局部对象,然后MyStruct也没有析构函数来释放申请的空间,所以向管理它的shared_ptr传递一个删除器来做这两件事。
shared_ptr的陷阱
不要写出独立的shared_ptr
关于独立的shared_ptr的意思及危害上面已经说出,遵守下面几点来避免这个错误
- 不要与裸指针混用
//错误场景1int *x(new int(10));shared_ptr<int> sp1(x);shared_ptr<int> sp2(x);//虽然sp1、sp2都指向x所指的内存,但他们是独立的,//会在其他shared_ptr还在使用内存的情况下就释放掉内存//失去了设计共享指针的意义//同时,使用裸指针x本身也是很危险的,x随时可能变成空悬指针而无从知晓
//错误场景2//函数接受一个共享指针参数void func(shared_ptr<int> sp);int *x(new int(10));//创建了一个指向x指针所指内存的共享指针,引用计数为1,是引用这块内存的唯一共享指针func(shared_ptr<int> (x));//离开函数即离开共享指针的作用域,这块内存即被删除
- 不要用p.get()的返回值为shared_ptr赋值
shared_ptr<int> sp1(new int(10));//sp2与sp1独立shared_ptr<int> sp2(sp1.get()),sp3;//sp3与sp1独立sp.reset(sp1.get());
谨慎使用p.get()的返回值
p.get()的返回值就相当于一个裸指针的值,不合适的使用这个值,上述陷阱的所有错误都有可能发生,遵守以下几个约定
不要保存p.get()的返回值
无论是保存为裸指针还是shared_ptr都是错误的
保存为裸指针不知什么时候就会变成空悬指针
保存为shared_ptr则产生了独立指针不要delete p.get()的返回值
会导致对一块内存delete两次的错误
记得向shared_ptr传递删除器
如果用shared_ptr管理非new对象或是没有析构函数的类时,应当为其传递合适的删除器
避免形成指针循环引用
循环引用
- shared_ptr的使用和陷阱
- shared_ptr的使用和陷阱
- boost::shared_ptr的多线程使用陷阱
- shared_ptr陷阱
- unique_ptr的使用和陷阱
- unique_ptr的使用和陷阱
- shared_ptr的使用心得
- 使用 shared_ptr 的一個問題代碼
- 学习笔记:shared_ptr陷阱
- 学习笔记:shared_ptr陷阱
- shared_ptr三个陷阱
- shared_ptr三个陷阱
- 学习笔记:shared_ptr陷阱
- shared_ptr 在 stl容器中排序的陷阱。
- Boost:使用shared_array和shared_ptr
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- 智能指针scoped_ptr,shared_ptr,weak_ptr和auto_ptr的使用
- java常用开发包(1)--log4j.jar
- 多条目显示
- Python(2)python中的注释,语句分类,变量,数据类型,多进制书写规则
- nyoj 字母统计
- jq 判断session值是否为空
- shared_ptr的使用和陷阱
- 在Eclipse中使用Maven插件创建Javaweb项目的教程
- 自己写的RxJava和Retrofit结合
- 学习资料(干货汇集)不断更新【更新于2017-9-17】
- Unity消息机制
- 最大子序列的三种求解方式
- 进程等待与wait&waitpid
- HDU-2602 Bone Collector 01背包
- springboot实现kaptcha验证码