背景介绍:

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 分析的更多相关文章

  1. [3] 智能指针std::auto_ptr

    [1]std::auto_ptr 对于编译器来说,智能指针实质是一个栈对象,而并非指针类型. 智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存. 所 ...

  2. 智能指针之auto_ptr和scoped_ptr

    部分参考地址https://blog.csdn.net/yanglingwell/article/details/56011576 auto_ptr是c++标准库里的智能指针,但是具有以下几个明显的缺 ...

  3. 智能指针之 auto_ptr

    C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理,该智能指针在C++11中已经被弃用,转而由unique_ptr替代, 那这次使用和实现,就具体讲一下auto_pt ...

  4. 智能指针std::unique_ptr

    std::unique_ptr 1.特性 1) 任意时刻只能由一个unique_ptr指向某个对象,指针销毁时,指向的对象也会被删除(通过内置删除器,通过调用析构函数实现删除对象) 2)禁止拷贝和赋值 ...

  5. C++ 智能指针 boost::scoped_ptr分析

    1.scoped_ptr的实现原理及特性 特性:scoped_ptr和auto_ptr类似,但最大的区别就是不能转让管理权限,也就是说scoped_ptr禁止用户进行拷贝和赋值 实现原理:如何才能禁止 ...

  6. 【C++深入浅出】智能指针之auto_ptr学习

    起:  C++98标准加入auto_ptr,即智能指针,C++11加入shared_ptr和weak_ptr两种智能指针,先从auto_ptr的定义学习一下auto_ptr的用法. template& ...

  7. 智能指针shared_ptr, auto_ptr, scoped_ptr, weak_ptr总结

    看这里: http://blog.csdn.net/lollipop_jin/article/details/8499530 shared_ptr可以多线程同时读,但是涉及到写,需要加锁. share ...

  8. 智能指针std::weak_ptr

    std::weak_ptr 避免shared_ptr内存泄漏的利器.

  9. C++的优秀特性6:智能指针

    (转载请注明原创于潘多拉盒子) 智能指针(Smart Pointer)是C++非常重要的特性.考虑如下一段使用简单指针(Plain Pointer)的代码: A* a = new A(); B* b ...

随机推荐

  1. vuex2 mapActions 报错 `unknown action type: xxxx`

    export const setBreadCrumb = ({ dispatch }, data) => { dispatch('SET_BREADCRUMB', data) } 当调用的时候报 ...

  2. OpenCV 学习笔记(7)vs2015+ffmpeg开发环境配置

    参考教程 https://blog.csdn.net/HUSTLX/article/details/51014307 1.在http://ffmpeg.zeranoe.com/builds/  下载最 ...

  3. MVVM架构方式

    一.概念 ①常见的架构方式或者开发思想还有MVC.MVP和MVVM,参考文章:MVC,MVP 和 MVVM 的图示 ②MVC:视图(View),指用户界面:控制器(Controller),指业务逻辑: ...

  4. python实现余弦相似度文本比较

    向量空间模型VSM: VSM的介绍: 一个文档可以由文档中的一系列关键词组成,而VSM则是用这些关键词的向量组成一篇文档,其中的每个分量代表词项在文档中的相对重要性. VSM的例子: 比如说,一个文档 ...

  5. mac 以多tab的方式打开

    让mac 始终以多tab的方式打开程序 背景: 开发中始终需要多个 项目 的方式进行处理, 但一直使用 `command + `` 的方式总是比较烦人, 有没有一个比较好的视图方式呢; 即我想在一个窗 ...

  6. Jmeter(四十七)_性能测试统计超时率

    概述 今天做一个性能测试的案例.需求中给出并发人数和业务时间段.根据2,5,8原则,统计响应超时率 实际场景 1:登录--考勤打卡--退出 2:并发人数200人,业务持续时间5分钟 3:要求登录响应时 ...

  7. 第08组 Alpha冲刺(1/4)

    队名 八组评分了吗 组长博客 小李的博客 作业博客 作业链接 组员1(组长) 过去两天完成了哪些任务 文字/口头描述 11月9号开小会安排alpha冲刺开始的工作,进行任务分工,具体见11.09会议记 ...

  8. Android相关视频

    Android架构师 层次分析 –从顶层到底层 洞察其原理https://www.bilibili.com/video/av59066641?t=132安卓/Android 逆向破解系统班 第2期 全 ...

  9. mac下使用java测试iOS推送

    首先mac下有很多现在的测试iOS推送软件,为什么要用java程序测试呢: 因为大多数后台推送服务可能是JAVA开发的,那么为了验证我们在MAC上导出的推送证书文件是否正确: 制作开发证书的iOS开发 ...

  10. Python示例项目学习

    原文地址:http://www.360doc.com/showweb/0/0/874025604.aspx 「 Python3 实现火车票查询工具 」   相信很多人学Python都是冲着它强大的爬虫 ...