
智能指针-----》auto_ptr
发布日期:2021-05-07 09:16:09
浏览次数:16
分类:技术文章
本文共 4875 字,大约阅读时间需要 16 分钟。
智能指针:
c11里面的四个智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr其中后三个是c11支持的,并且第一个已经被c11弃用。本博客主要讲auto_ptr,后面会持续更新其他智能指针。c98中auto_ptr所做的事情就是动态分配对象以及当对象不再需要时自动执行清理。
举例: 以下不使用auto_ptr的函数就有可能发生内存泄漏:void fun(){ Object* op = new Object(10); cout << op->Value() << endl; if (op->Value() == 10) { return;//内存泄漏 } delete op;}
使用auto_ptr指针很好的避免了内存泄漏:函数结束的时候,auto_ptr调用析构函数,可以释放资源。
void fun(){ auto_ptr
auto_ptr 源码:
#include#include using namespace std;namespace wwn{ template class auto_ptr { private: T* _Ptr; bool _Owns;//使用权 public: typedef T element_type; explicit auto_ptr(T* p = nullptr) :_Owns(p!=nullptr),_Ptr(p){ } auto_ptr(const auto_ptr & _Y) :_Owns(_Y._Owns), _Ptr(_Y.release){ } //错误:按照设计的先后顺序初始化,所以会先执行_ptr(_Y.release) auto_ptr& operator=(const auto_ptr & _Y) { if (this != &_Y) { if (_Ptr != _Y.get()) { if (_Owns) delete _Ptr; _Owns = _Y._Owns; } else if(_Y._Owns) { _Owns = true; } _Ptr = _Y.release(); } return *this; } ~auto_ptr() { if (_Owns) { delete _Ptr; } _Ptr = NULL; } void reset(T* p = NULL) { if (_Owns) { delete _Ptr; } _Ptr = p; } T* get() const { return _Ptr; } T & operator*() const { return (*get()); } T* operator->()const { return get(); } T* release()const { T* tmp = NULL; if (_Owns) { ((auto_ptr *)this)-> _Owns = false; tmp = _Ptr; ((auto_ptr *)this)->_Ptr = NULL; } return tmp; } };}class Object{ private: int value;public: Object(int x=0):value(x){ } ~Object(){ } int& Value() { return value; } const int& Value()const { return value; } void Print() const{ cout << value << endl; }};void fun1(){ //vector >vec; //错误,绝对不可以这样写 vector vec; vec.push_back(new int(10)); vec.push_back(new int(20));}void fun(){ wwn::auto_ptr
注意:oap.{ get() ; operator() ; operator() ; ~auto_ptr() ; _ptr} 智能指针 . 后面跟的是智能指针自己的方法以及成员。

oap->{ Value() ; value ; ~Object() } 智能指针-> 后面跟的是智能指针所指对象的属性和方法。

opa->Print();(*opa).Print();//两个是等价的
auto_ptr的使用以及弃用原因
- 构造函数与析构函数 auto_ptr在构造时获取对某个对象的所有权,在析构时时释放该函数 我们可以这样使用auto_ptr来提高代码的安全性
int* p=new int(0);auto_ptr ap(p);
这样就不必关心何时是释放p,也不用担心发生异常会有内存泄露。
弃用原因 1)因为auto_ptr析构的时候会删除他所拥有的对象,所以不同的auto_ptr不能指向同一个对象。如下:int* p=new int(0);auto_ptr ap1(p);auto_ptr ap2(p);
这样在ap1和ap2在析构时都会去删除p,两次删除同一个对象的行为在c++标准中是未定义的。
2)String *str=new String[10];auto_ptrap(str);
考虑以上情况,auto_ptr在析构函数中删除针织用的是delete,而不是delete[],所以我们不应该用auto_ptr来管理一个数组指针。
3)构造函数的explicit关键字有效阻止从一个“裸”指针隐式转换成auto_ptr; 2. 拷贝构造与赋值 与引用计数型指针不同,auto_ptr要求其对“裸”指针的完全占有。也就是一个“裸”指针只能同一时刻只能被一个auto_ptr拥有,所以在拷贝构造或者赋值操作时,要做的事所有权的转移。即就是使源对象失去所有权,所以拷贝构造函数和赋值函数的参数为引用而不是常引用。当然,因为一个auto_ptr同一个时刻只能指向一个裸指针,所以应该先释放原来拥有的对象。 弃用原因 1)因为一个auto_ptr被拷贝或者赋值后,失去了对原对象的所有权,这个时候,对这个auto_ptr的提领操作是不安全的。如下:int *p=new int(0);auto_ptr ap1(p);auto_ptr ap2=ap1;cout<<*ap1;//错误,此时ap1已经失去对p指针的拥有权
还有一种较为隐蔽的情形,如下:
void fun(auto_ptr ap){ cout<<*ap;}auto_ptr ap1(new int(0));fun(ap1);cout<<*ap1;//错误,调用fun函数的时候将其对象的拥有权转移给函数的形参ap,所以此时ap1不再拥有对象
该情况太隐蔽,将auto_ptr作为函数参数按值传递一定是要避免的,因为无法预料函数会对auto_ptr做什么,如果在该过程中失去了对对象的拥有权,这可能导致致命的执行期错误。
2)可以看到拷贝构造函数和赋值函数都提供了一个成员模板在不覆盖“正统”版本的情况下实现auto_ptr的隐式转换,如下:class Object{ };class Base:public Object{ };
那么下面代码就可以实现从auto_ptr到auto_ptr的隐式转换。
auto_ptr
3)因为auto_ptr不具有值语义,所以auto_ptr不能被用在stl标准容器中。
举例如下:
vector
- 提领操作 提领操作有两个操作,一个是返回其所拥有的对象的引用,另一个是实现通过auto_ptr调用其所拥有对象的成员,如下:
class Base{ void fun(){ };}auto_ptr ap(new Base());(*ap).fun();ap->fun();
首先我们要确保这个智能指针确实拥有某个对象,否则,这个操作的行为即对空指针的提领是未定义的。
使用auto_ptr的注意事项
- auto_ptr不能指向数组
- auto_ptr不能共享所有权
- auto_ptr不能通过赋值操作来初始化
- auto_ptr不能作为容器来使用
- auto_ptr不能作为容器的成员
- 不能把一个原生指针给两个智能指针对象管理
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月10日 05时42分38秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
vue通过better-scroll 封装自定义的下拉刷新组件
2019-03-05
android解决:使用多线程和Handler同步更新UI
2019-03-05
vue自定义封装Loading组件
2019-03-05
解决移动端项目中苹果ios和安卓android手机点击输入框网页页面自动放大缩小
2019-03-05
vs code 正则表达式 visual Studio code vscode
2019-03-05
Element UI 中动态路由的分析及实现
2019-03-05
使用springMVC配置视图管理器后找不到指定的页面
2019-03-05
关于js中对于Promise的深入理解
2019-03-05
对于js中的this指向的深入理解
2019-03-05
杭电 2007 平方和与立方和(输入数据的大小顺序并不能默认)
2019-03-05
杭电oj 2015 偶数求和
2019-03-05
蓝桥杯基础练习 特殊回文数 (原来暴力破解这么直接……)
2019-03-05
Qt 从文本文件中读入一行内容但不包含换行符
2019-03-05
【STL】容器适配器之stack、queue用法总结
2019-03-05
社区AMA:CasperLabs是如何从众多智能合约平台脱颖而出的
2019-03-05
十大排序算法之三:插入排序(Python)
2019-03-05
利用Python实现链表
2019-03-05
利用Python实现循环队列
2019-03-05
十大排序算法之四:希尔排序(Python)
2019-03-05
利用递归实现二叉树的前中后序遍历(Python)
2019-03-05