C++11 智能指针——(C++98)auto_ptr
来源:互联网 发布:华为mate9下载软件 编辑:程序博客网 时间:2024/05/17 08:56
lofter地址:http://willkall.lofter.com/
C++11从boost库中引入了unique_ptr, shared_ptr, weak_ptr,并舍弃了c98的auto_ptr。
一、c++98 auto_ptr(参见《C++标准程序库》——孟岩/侯捷译)
C++标准程序库描述:“auto_ptr是一种智能指针,帮助程序员防止'被异常抛出时发生资源泄露'”。它在对象析构的时候自动释放资源,并模仿了原始指针的操作,重载了operator*和operator->,允许程序员向使用原始指针一样使用auto_ptr(但是没有重载所有的指针算术运算),并减少程序员显示的处理异常发生时代码的复杂度与失误。
注意:auto_ptr是严格的拥有权类智能指针,使用时注意以下几点
- auto_ptr之间不能共享拥有权
- auto_ptr对象通过赋值或构造转移拥有权,一旦拥有权转移,此auto_ptr所拥有的将是一个原始指针
- auto_ptr不适用于array
- auto_ptr不满足STL对容器元素的要求,因此不适用于STL容器。因为在拷贝和赋值之后,新的auto_ptr和旧的auto_ptr对象并不相等。
- 如果要阻止拥有权的转移,则应该在停止转移之前,将auto_ptr声明为const
- 不要使用auto_ptr的引用作为实参:因为你不知道拥有权到底有没有转移。如果你不需要转移拥有权,请使用const auto_ptr<class> &
1.auto_ptr的初始化
auto_ptr不允许使用一般的指针赋值来初始化,必须使用其构造函数来初始化。因为“根据一般指针生成一个auto_ptr”的那个构造函数被声明为explicit(禁止单参构造函数用于自动型别转换)
std::auto_ptr<ClassA> ptr1(new ClassA);//OKstd::auto_ptr<ClassA> ptr2 = new ClassA;//ERROR2.auto_ptr拥有权转移
程序员必须防范一个原始指针被两个auto_ptr所拥有,且在auto_ptr丧失了拥有权后不可以再次使用此auto_ptr
//initialize an auto_ptr with a new obj std::auto_ptr<ClassA> ptr1(new ClassA); //copy the auto_ptr-->transfers the ownership from ptr1 to ptr2 std::auto_ptr<ClassA> ptr2(ptr1); //ptr1拥有权转移,以后不可再对ptr1使用operator*以及operator-> //like copy std::auto_ptr<ClassA> ptr3 = ptr2; //ptr2拥有权转移给ptr3,以后不可再对ptr2使用operator*以及operator-> std::auto_ptr<ClassA> ptr4(new ClassA); //create a new auto_ptr::ptr4 ptr3 = ptr4; //here ptr3 delete the obj it own ,and then ptr4 transfers the ownership to ptr3。ptr4 own a nullptr
3.auto_ptr之起点和终点
auto_ptr拥有权的转移特性使得auto_ptr可以方便的实现数据的产生与销毁:在某函数中创建auto_ptr并以值形式返回,或者接受一个以值传递的auto_ptr对象,但不返回auto_ptr。
void sink(auto_ptr<ClassA>);//end the ownership transfer,delete source auto_ptr<ClassA> generate(void);//generating an auto_ptrgenerate()每次调用都new一个 classA对象,并将对象以及拥有权一起转移个调用端
sink(auto_ptr<classA>)每次调用有传入一个auto_ptr对象,但是不再返回auto_ptr。因此传入对象的拥有权在sink函数不再转移,并且auto_ptr拥有的资源也得到释放。
4.使用const auto_ptr
const auto_ptr意味着你不可以更改这个auto_ptr的拥有权——即你不能转移它也不能对其重新赋值。const auto_ptr比较类似于常指针(T *cosnt p)。
const auto_ptr<int> ptr(new int); *ptr = 42;//OK auto_ptr<int> ptr1(new int); ptr1 = 58; ptr = ptr1;//wrong,could not change ptr ownership,COMPLIE-TIME ERROR
5.auto_ptr源码注解(此处仅列出部分源码,完整源码见auto_ptr.h)
template<typename _Tp>class auto_ptr{private: _Tp* _M_ptr;public: typedef _Tp element_type; explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } //禁止原始指针直接赋值时的隐式类型转换 auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { } //释放拥有权并置其拥有的原始指针为NULL template<typename _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { } //2016-03-05 ???? auto_ptr&operator=(auto_ptr& __a) throw() //释放并转移拥有权 { reset(__a.release()); return *this; } template<typename _Tp1> //2016-03-05 为啥要声明一个_TP1类型???? auto_ptr&operator=(auto_ptr<_Tp1>& __a) throw() { reset(__a.release()); return *this; } ~auto_ptr() { delete _M_ptr; } //析构时释放资源——不适用于数组!! element_type& operator*() const throw() { _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); return *_M_ptr; } element_type* operator->() const throw() { _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); return _M_ptr; } element_type* get() const throw() { return _M_ptr; } //获取原始指针——获取后切勿delete!!!! element_type* release() throw() //显示的释放拥有权并置拥有的原始指针为NULL { element_type* __tmp = _M_ptr; _M_ptr = 0; return __tmp; } void reset(element_type* __p = 0) throw() //释放拥有权,并获取新的拥有权——可以自赋值 { if (__p != _M_ptr) { delete _M_ptr; _M_ptr = __p; } }};
2016-03-06追加(纯属娱乐):
auto_ptr初始化的时候并不一定需要使用new class来初始化,直接使用一个原始指针即可。但是这样操作很可能出现问题——若用来初始化的原始指针不是一个new出来的存在于堆内存中的对象,则在后续的使用中会造成非法delete(对非new分配的指针调用delete)。以下为一个代码示例:
#include <iostream>#include <memory>using namespace std;void stack_test(int *ip){ auto_ptr<int> aip(ip);}int main(){ int *ip = new int(15); stack_test(ip); int c = 49; int *ip1 = &c; stack_test(ip1); cout << "*api = " << *ip << endl; cout << "*api2 = " << *ip1 << endl; return 0;}
以下为运行结果:
程序可以正常运行(运气不错),但*api得的值已经被覆盖,该指针已经无效。
说明:
1.不管是堆上的还是栈上的指针,都可以用来初始化auto_ptr
2.使用方法1可以使一个原始指针被多个auto_ptr所拥有(这样做非常危险)
3.栈上的内容并没有被修改——是否是因为没有调用delete或者是其他原因?因为c是栈上的元素,无法调用delete删除,在其生命周期中也不会被非法覆盖,所以*api2打印结果正常。但不知道auto_ptr对传入的栈上的指针是如何处理的?
4.另外此处还可说明:auto_ptr析构只是delete并置其拥有的原始指针为nullptr,但是用来初始化它的原始指针值(也就是其指向的地址)是不变的。
5.对上述代码尝试进行try...catch操作,但是没有捕获到异常(是否感到很不正常?)
- C++——模版:智能指针auto_ptr
- 【C++】智能指针auto_ptr
- c++ auto_ptr智能指针详解
- 【C/C++】智能指针auto_ptr,share_ptr,unique_ptr
- 【C/C++和指针】auto_ptr智能指针
- C/C++——跟我重写智能指针auto_ptr模版类
- 【C++】智能指针auto_ptr的简单实现
- C++:auto_ptr智能指针的用法
- 【C++】智能指针auto_ptr/unique_ptr/shared_ptr/weak_ptr!!!
- C++11 智能指针——(C++98)auto_ptr
- c++—智能指针
- C++——智能指针
- C/C++:智能指针原理(运算符重载)、使用auto_ptr<A>
- C++——auto_ptr类
- C++——auto_ptr类
- C++——auto_ptr类
- C++:Boost智能指针——scoped_ptr
- C++——智能指针简介
- Java关键字介绍之this与super
- Codeforences #334 C(div2)
- Nim Game
- java采用MD5加密解密
- 百度地图总结第二篇--POI检索功能
- C++11 智能指针——(C++98)auto_ptr
- 利用系统自带的UITabBarController纯代码搭建TabBar
- HDOJ 1220-Cube【数学推理】
- j2ee 使用db.properties连接mysql数据库
- 屏幕截图
- 求较大数的阶乘
- Android,iOS打开手机QQ与指定用户聊天界面(联系客服)
- UESTC P酱的冒险旅途 785 (规律模拟)
- 在水晶报表中使用Code128条形码