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 ...
随机推荐
- 学习:Windows数据类型
WINDOWS API中出现的常见的数据类型有以下几种: 1.DWORD:DWORD用于表示无符号整型的数据类型,实际名为double word,32位 2.HANDLE:HANDLE为32位的数据类 ...
- MongoDB shell 0 集合方法
方法名 描述 db.collection.aggregate() 聚合,主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果 db.collection.bulkWrite() 批量写入 ...
- 大文件上传组件webupload插件
之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...
- python的虚拟环境管理工具venv使用方法介绍及与nodejs的包管理方式对比
一.nodejs 包管理方式 我们知道, nodejs的包管理工具npm可以安装项目所需要的包,安装方法及区别如下: npm i module_name -g 全局安装 npm i module_na ...
- matlab 只安装部分产品
- 洛谷P1962 斐波那契数列题解
题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请 ...
- luogu P1447 [NOI2010]能量采集 欧拉反演
题面 题目要我们求的东西可以化为: \[\sum_{i=1}^{n}\sum_{j=1}^{m}2*gcd(i,j)-1\] \[-nm+2\sum_{i=1}^{n}\sum_{j=1}^{m}gc ...
- [技术博客]使用CDN加快网站访问速度
[技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...
- 认真分析mmap:是什么 为什么 怎么用(转)
阅读目录 mmap基础概念 mmap内存映射原理 mmap和常规文件操作的区别 mmap优点总结 mmap相关函数 mmap使用细节 回到顶部 mmap基础概念 mmap是一种内存映射文件的方法,即将 ...
- 让ie10/11支持非单页面的vue/es6
为了满足某些客户的要求,最近让前端同学实现了ie 10(windows 7)/11(windows 10)支持多页面的vue/es6,基本参考如下: https://www.cnblogs.com/n ...