背景介绍:

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. 学习:STL概念学习

    STL初识: 为了建立数据结构和算法的一套标准,诞生了STL STL基本概念: STL(Standard Template Library,标准模板库) STL 从广义上分为: 容器(containe ...

  2. linux学习15 Linux系统用户和组全面讲解

    一.用户,组和权限管理 1.多用户(Multi-tasks),多任务(Multi-Users).对计算机而言,每一个使用者就是一个用户. 2.每个使用者: a.用户标识,密码: 认证(Authenti ...

  3. blessed-contrib 开发终端dashboard 的几点说明

    以前有说过blessed-contrib 这个很不错的终端dashboard 开发框架,以下是使用中的一些问题 中文编码 模式是不支持中文编码的,但是 我们可以在初始化的时候指定unicode编码 s ...

  4. minio gataway 模式快速提供s3 兼容的文件服务

    实际很多场景我们已经有了遗留系统的文件存储方式(ftp,或者共享目录),但是这个方式可能不是很好,对于web 不是很友好 实际上minio 也提供了gateway 的模式,可以方便快速的将遗留系统的存 ...

  5. 什么是JSON Web Token

    JSON Web Token(JWT)是一个基于 RFC 7519 的开放数据标准,它定义了一种宽松且紧凑的数据组合方式,使用 JSON  对象在各应用之间传输加密信息.该 JSON 对象可以通过数字 ...

  6. Using the Repository and Unit Of Work Pattern in .net core

    A typical software application will invariably need to access some kind of data store in order to ca ...

  7. cf1187解题报告

    cf1187解题报告 cf A 去掉都有的,剩下的取最大值+1 #include <bits/stdc++.h> #define int long long using namespace ...

  8. centos7 出现“FirewallD is not running”

    原因:没有开启防火墙 #提示没有开启防火墙服务,–permanent #永久生效,没有此参数重启后失效 [root@uJZ ~]# firewall-cmd --permanent --zone=/t ...

  9. shell 查找字符串中字符出现的位置

    #!/bin/bash a="The cat sat on the mat" test="cat" awk -v a="$a" -v b=& ...

  10. Jmeter(四十八)_动态线程分析HTML测试报告

    概述 jmeterGUI模式下,性能测试的结果往往误差很大,因为GUI本身就会消耗一部分资源.所以我们常常用命令行去跑性能脚本,得出结果 同时,jmeter在命令行下还可以生成多维度的测试报告,里面包 ...