智能指针

目录

基础部分

1、智能指针的引入

2、什么是智能指针

一、auto_ptr 自动指针

1、出现

2、原理

3、注意事项

二、scoped_ptr 守卫指针

1、出现

2、方法

三、shared_ptr  共享指针

1、出现

2、原理

3、循环引用

四、weak_ptr  弱指针

1、出现

2、原理

五、unique_ptr 

补充:


基础部分

1、智能指针的引入

在编程中常会有动态内存的开辟,而用完后会忘记释放;

在逻辑处理时也要十分严谨;

野指针的问题。因为一不小心就会有内存泄漏问题。内存泄漏会引发占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。智能指针就是为了防止内存泄漏而引出的。

2、什么是智能指针

智能指针是一个类,用它的对象管理着申请的内存空间,并通过作用域、声明周期来保证申请内存的释放,从而防止出现内存泄漏

所谓的智能指针就是帮你管理指针,用完后自动释放  //手动开辟,系统释放

一、auto_ptr 自动指针

1、出现

C++98时提出的,效果不是很好,于是才出现了其他的智能指针

2、原理

所有权唯一

管理权转移(新的指针在拷贝构造或者赋值原来的指针时,会把原来的指针置为NULL,让新指针指向原来指针指向的空间,所以称之为自动指针)所以访问原来的指针时,程序会崩溃

3、注意事项

(1)auto_ptr不能共享所有权

(2)auto_ptr不能指向数组

(3)auto_ptr不能作为容器的成员

(4)不能通过赋值操作来初始化auto_ptr

(5)不要把auto_ptr放入容器

所以尽量任何情况下也不用auto_ptr

二、scoped_ptr 守卫指针

1、出现

因为auto_ptr的各方面都不行(在拷贝构造或者赋值运算后,访问原来的指针程序就会崩溃),scoped_ptr就是为了避免这种奔溃才出现的。scoped_ptr直接不允许进行拷贝构造和赋值运算符重载,故而没有释放两次导致崩溃的事情发生。

2、方法

将拷贝构造和赋值运算符重载的声明给成私有,不给定义

假设我们在类外运用了拷贝构造和赋值运算,编译器会检查,发现这是不正确的。错误提示:无法访问private成员

三、shared_ptr  共享指针

1、出现

shared_ptr是可以拷贝和赋值的,通过对管理一块空间的智能指针进行计数,只有当count == 0时,再进行释放

2、原理

所有权不唯一  

shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数,当新增一个shared_ptr对该对象进行管理时,就将该对象的引用计数加一;减少了一个shared_ptr对该对象进行管理时,就将该对象的引用计数减一,如果该对象的引用计数为0的时候,说明没有任何指针对其管理,才调用delete释放其所占的内存。这也是最常用的一种

3、循环引用

shared_ptr可能会出现循环引用的问题

我们实例化两个shared_ptr对象,pa指向一块空间,pb指向另一块空间。那么按照shared_ptr的机制,此时pa和pb指针所指向的空间计数count都为1。但是假设两个shared_ptr的对象中还有next指针和prev指针。我们让pa中的next指针指向pb指向的空间时,pb所指向的空间中的count计数变为2;pb的prev指针指向pa指向的空间,pa所指向的空间计数count也变成了2.

当pa释放时,它所指向的空间计数count必须为0,此时,pb中的prev指针也指向该空间,只有当pb中的prev被释放了,pa才能被释放;

要释放pb中的prev指针,它指向的空间计数器count必须为0,此时pa中的next指针也指向该空间,只有当pa中的next指针被释放了,pb才能释放

这就是存在的循环引用问题

四、weak_ptr  弱指针

1、出现

因为shared_ptr有循环引用的问题,weak_ptr就是为了解决循环引用而产生的,weak_ptr不会增加shared_ptr所指向空间的引用计数

2、原理

弱指针并不修改对象的引用计数,这意味着弱指针引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别,弱指针能检测到所管理的对象是否已经被释放,从而避免访问非法内存

五、unique_ptr 

类似于一个动态开辟的数组

由于可以用vector实现,所以用的不多,并且不存在于boost库

补充:

1、内存泄漏(memory leak)

指一块被分配的内存既不能使用,又不能回收,直到进程结束

内存泄漏: 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。 
一般我们所说的内存泄漏是指堆内存的泄漏,堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完成之后必须显示释放内存。应用程序一般使用malloc、realoc、new等函数从堆中分配到一块内存块,使用完成后,程序必须负责相应的释放。在C中使用free(),C++中delete、delete[]、free()。而Java中由于垃圾回收机制不用手动释放。 
如果内存不能释放,这块内存就不能再次使用,我们就说这块内存泄漏了。

2、以发生的方式来分类,内存泄漏可以分为4类

(1)常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。 

(2)偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。 

(3)一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。 

(4)隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到.

3、内存溢出(out of memory)

内存溢出:程序要求的内存,超出了系统所能分配的范围。如:我们用一个int型4字节的数据来装一个float型8字节的数据,就会产生内存溢出。不过我们在编程是可以强制类型转换int XX = (int)float;只取float 4字节数据给int.

4、RAII

RAII称为“资源获取就是初始化”,是c++等编程语言常用的管理资源

避免内存泄露的方法。它保证在任何情况下,

使用对象时先构造对象,最后析构对象。

5、boost库

了解智能指针就需要了解boost库,C++11引入的智能指针标准中,参考了boost库中对智能指针的实现

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值