C++ 智能指针 std::auto_ptr 分析
背景介绍:
RAll机制
定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,从而保证资源的正确初始化和清理
ps:智能指针就是RAll机制的一种应用,智能指针从根本上来说是一个对象
1.auto_ptr是什么?
auto_ptr是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分配给两个拥有者,当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放,即使发生异常,通过异常栈的展开过程也能将动态内存释放,auto_ptr不支持new 数组
ps:头文件:#include<memory>
2.初始化auto_ptr的方法
1)构造函数
将已存在的指向动态内存的普通指针作为参数来构造
int *p=new int(33); auto_ptr<int> aptr(p);
直接构造
auto_ptr<int> aptr(new int(33));
2)拷贝构造
利用已经存在的智能指针来构造新的智能指针
auto_ptr<string> p1(new string("name"));
auto_ptr<string> p2(p1);
注意:因为一块动态内存只能由一个智能指针独享,所以在拷贝构造和赋值时都会发生拥有权转移,在此拷贝构造过程中,p1将失去对字符串内存的所有权,而p2获得,对象销毁时,p2负责内存的自动销毁
3)赋值
利用已经存在的智能指针来构造新的智能指针
auto_ptr<string> p1(new string("name"));
auto_ptr<string> p2(new string("sex")); p1=p2;
在赋值之前由p1指向的对象被删除,赋值之后p1拥有字符串sex的内存所有权,p2不再被用来指向sex字符串对象
ps:可以直接定义一个空的智能指针,默认值为0
3.防止两个auto_ptr对象拥有同一个对象(同一块内存)
因为auto_ptr的内存所有权是独占的,所以以下代码存在问题
int *p=new int(10); auto_ptr<string> p1(p);
auto_ptr<string> p2(p);
因为p1和p2都认为p是由它管,在析构时都试图删除p,两次删除同一个对象的行为在C++标准中是未定义的,我们必须防止这样使用auto_ptr
4.警惕auto_ptr作为参数
1)按值传递时,函数的调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr(拷贝构造),这样传入的实参就其对原对象的所有权,而该对象在函数退出时会被局部的auto_ptr删除,样例如下:
void f(auto_ptr<int> aptr)
{
cout<<*aptr<<endl;
}
int main()
{
auto_ptr<int> aptr(new int(10));
f(aptr);
cout<<*aptr<<endl;//错误,经过f函数调用,原有的aptr已经不再拥有任何对象了 }
2)参数为引用或指针,虽然不会存在上述的拷贝过程,但是我们并不知道函数对传入的auto_ptr做了什么,如果其中的某种操作使其失去了对象的所有权,那么还是会导致致命的执行错误
结论:const reference是auto_ptr作为参数传递的底线
5.auto_ptr不能初始化为指向非动态内存
因为delete表达式被应用在指向非动态内存的指针上,这是C++未定义的程序行为
6.auto_ptr常用的成员函数
1)get:返回auto_ptr指向的那个对象的内存地址
int main()
{
int *p=new int(10);
cout << "the adress of p: "<< p << endl; auto_ptr<int> aptr(p); cout << "the adress of aptr: " << &aptr << endl;
cout << "the adress of the object which aptr point to: " << aptr.get() << endl; } /*
程序运行结果:
the adress of p: 0xb50f80
the adress of aptr: 0x69fed8
the adress of the object which aptr point to: 0xb50f80
*/
2)reset:重新设置auto_ptr指向的对象,类似于赋值操作,但是赋值操作不允许将一个普通指针直接赋值给auto_ptr,而reset允许
reset(0)可以释放对象,销毁内存
int main()
{
auto_ptr<string> aptr(new string("name"));
aptr.reset(new string("sex")); cout<<*(aptr.get())<<endl;
cout<<*aptr<<endl;
}
/*
程序运行结果:
sex
sex
*/
3)release:返回auto_ptr指向的那个对象的内存地址,并且释放这个对象的所有权
用此函数初始化auto_ptr可以避免两个auto_ptr对象指向同一个对象的情况
int main()
{
auto_ptr<string> aptr(new string("name")); auto_ptr<string> aptr1(aptr.get());//这是两个auto_ptr拥有同一个对象
auto_ptr<string> aptr2(aptr.release());//release可以先释放所有权,这样就不会指向同一个对象
}
该函数不会释放对象,仅仅会归还所有权
7.千万不要把auto_ptr对象放在容器中
容器要求对象可以进行安全的赋值操作,可以将一个对象拷贝到另外一个对象,从而获得两个独立的逻辑上相同的拷贝,尤其是当一个对象被拷贝到另外一个对象后,原来的对象不会改变,但是很显然,auto_ptr不支持这个性质
使用总结:
1)两个auto_ptr对象不会同时指向同一个内存,要明白两个auto_ptr对象赋值会发生什么
2)auto_ptr对象存储的指针应该为NULL或者指向一个动态内存块
3)auto_ptr对象存储的指针应该指向单一物件(是new出来的,而不是new[]出来的,不支持指向指针数组)
4)千万不要把auto_ptr对象放在容器中
5)当将auto_ptr作为参数传递时,const reference是auto_ptr作为参数传递的底线
结论:使用一个auto_ptr的限制很多,还不能用来管理堆内存数组,使用不当会引发很多的问题,其中一些设计也不符合C++设计的思想,所以产生了boost的智能指针,boost的智能指针可以解决上面的问题!下节将讨论boost智能指针
auto_ptr的本质是管理权限的转移!
C++ 智能指针 std::auto_ptr 分析的更多相关文章
- [3] 智能指针std::auto_ptr
[1]std::auto_ptr 对于编译器来说,智能指针实质是一个栈对象,而并非指针类型. 智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存. 所 ...
- 智能指针之auto_ptr和scoped_ptr
部分参考地址https://blog.csdn.net/yanglingwell/article/details/56011576 auto_ptr是c++标准库里的智能指针,但是具有以下几个明显的缺 ...
- 智能指针之 auto_ptr
C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理,该智能指针在C++11中已经被弃用,转而由unique_ptr替代, 那这次使用和实现,就具体讲一下auto_pt ...
- 智能指针std::unique_ptr
std::unique_ptr 1.特性 1) 任意时刻只能由一个unique_ptr指向某个对象,指针销毁时,指向的对象也会被删除(通过内置删除器,通过调用析构函数实现删除对象) 2)禁止拷贝和赋值 ...
- C++ 智能指针 boost::scoped_ptr分析
1.scoped_ptr的实现原理及特性 特性:scoped_ptr和auto_ptr类似,但最大的区别就是不能转让管理权限,也就是说scoped_ptr禁止用户进行拷贝和赋值 实现原理:如何才能禁止 ...
- 【C++深入浅出】智能指针之auto_ptr学习
起: C++98标准加入auto_ptr,即智能指针,C++11加入shared_ptr和weak_ptr两种智能指针,先从auto_ptr的定义学习一下auto_ptr的用法. template& ...
- 智能指针shared_ptr, auto_ptr, scoped_ptr, weak_ptr总结
看这里: http://blog.csdn.net/lollipop_jin/article/details/8499530 shared_ptr可以多线程同时读,但是涉及到写,需要加锁. share ...
- 智能指针std::weak_ptr
std::weak_ptr 避免shared_ptr内存泄漏的利器.
- C++的优秀特性6:智能指针
(转载请注明原创于潘多拉盒子) 智能指针(Smart Pointer)是C++非常重要的特性.考虑如下一段使用简单指针(Plain Pointer)的代码: A* a = new A(); B* b ...
随机推荐
- 数据库plsql配置
https://jingyan.baidu.com/article/d8072ac4957b28ec95cefd9f.html
- Bzoj 3343: 教主的魔法(分块+二分答案)
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MB Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息 ...
- 理解 IO_WAIT 并且了解利用包括 top htop iotop iostat 工具来查看 IO 性能
今天继续拜读「深入浅出计算机组成原理」专栏,觉得讲 IO_WAIT 这篇很有意思,正好可以结合前面的一篇讲物理硬件存速度的一块儿看. 现在我们看硬盘厂商出品的性能报告,通常会看到两个指标,一个是响应时 ...
- 基于centos搭建微信小程序服务,配置及数据库等
基于centos搭建小程序, ps:请提前20天准备将域名备案,申请ssl证书 实验上机地址:https://cloud.tencent.com/developer/labs/lab/10004 准备 ...
- mac 搭建Java Spring boot 环境(eclipse)
安装 下载安装Springboot 安装完成后,创建项目 1. 2. 3. 完成创建!
- CSS样式的引入方式
test.css div{ color:yellow; } 在html中引入 <link href="test.css" type="text/css" ...
- 安装和启动ElasticSearch服务遇到的几个问题
首先安装和启动服务的教程是参考文章:ES入门之一 安装ElasticSearch 然后在最后的启动es服务时遇到了几个小问题,因此在这里记录一下. 因为我对linux并不是很熟悉,因此文中如果有说错的 ...
- 【转】vim复制与粘贴
用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标移动到要复制的文本开始的地方,按v进入可视模式.2. 将光标移动到要复制的文本的结束的地方,按y复制.此时vim会自动将 ...
- MyBatis(十一):Mybatis 动态SQL语句完成多条件查询
之前文章中对in的用法做过讲解:<MyBatis(四):mybatis中使用in查询时的注意事项> 实际上对于多个参数的用法也是这是注意的: 多参&if判空&List集合判 ...
- crc64
oss2\models.py class PartInfo(object): """表示分片信息的文件. 该文件既用于 :func:`list_parts < ...