【C++进阶】智能指针

文章目录

  • 为什么需要智能指针?
  • 内存泄漏
    • 什么是内存泄漏,内存泄漏的危害
    • 内存泄漏分类(了解)
    • 如何避免内存泄漏
  • 智能指针的使用及原理
    • smart_ptr
    • auto_ptr
    • unique_ptr
    • shared_ptr
      • 线程安全的解决
      • 循环引用
    • weak_ptr
  • 删除器

为什么需要智能指针?

我们先来看一段代码:
【C++进阶】智能指针_第1张图片

大家觉得这段代码有什么问题?
发生了,内存泄漏。
【C++进阶】智能指针_第2张图片

因为p1,p2,p3指向的空间没有释放掉导致的。这就是异常安全问题。那要怎么解决呢?我们下面再回答。

内存泄漏

什么是内存泄漏,内存泄漏的危害

【C++进阶】智能指针_第3张图片
【C++进阶】智能指针_第4张图片

内存泄漏分类(了解)

  • 堆内存泄漏(Heap leak)
    堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak
  • 系统资源泄漏
    程序使用系统分配的资源比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定

如何避免内存泄漏

【C++进阶】智能指针_第5张图片

智能指针的使用及原理

【C++进阶】智能指针_第6张图片

smart_ptr

【C++进阶】智能指针_第7张图片
那么smart_ptr能解决上面遗留的问题吗?答案是可以的。
【C++进阶】智能指针_第8张图片
【C++进阶】智能指针_第9张图片
那么这个smart_ptr还有一些什么问题呢?
【C++进阶】智能指针_第10张图片

没错就是拷贝构造或者拷贝赋值的时候就会出问题,因为析构的时候同一块空间会被析构两次,这时候就会报错。那么该怎么解决呢?

auto_ptr

这时候就有人提出了管理权转移的思想来解决这个问题。
【C++进阶】智能指针_第11张图片
【C++进阶】智能指针_第12张图片
【C++进阶】智能指针_第13张图片
大家可以看到auto_ptr很好的解决了上面的问题,但是auto_ptr自身有一个很大的问题大家知道吗?就是悬空问题。
【C++进阶】智能指针_第14张图片
从上图可以看出p1变成悬空指针,且程序无法正常运行。
从中可以看出auto_ptr是一个失败的设计,并且很多公司都禁止使用auto_ptr.

unique_ptr

经过上面的尝试发现不行后,有人就想出了一个简单粗暴的办法,我直接防拷贝不就好了,也不用想那么多。
【C++进阶】智能指针_第15张图片
【C++进阶】智能指针_第16张图片

shared_ptr

但是要是我们真的需要多个指针,管理一块空间那该怎么解决之前的那个问题呢?这时候就用到了shared_ptr。
shared_ptr的思想是用引用计数来解决多个指针指向同一块空间的问题。
【C++进阶】智能指针_第17张图片
【C++进阶】智能指针_第18张图片
【C++进阶】智能指针_第19张图片
从上面我们可以看到,shared_ptr解决了之前的问题。那么上面实现的shared_ptr还有什么问题?线程安全问题。
【C++进阶】智能指针_第20张图片
【C++进阶】智能指针_第21张图片

我们可以看到,当n较小的时候并不会发生线程安全问题,但是当比较大的时候呢?
【C++进阶】智能指针_第22张图片
我们可以看到当n为10万的时候就发生了线程安全问题。
所以我们应该加锁。

线程安全的解决

【C++进阶】智能指针_第23张图片
【C++进阶】智能指针_第24张图片
我们可以看到加锁后,引用计数变的正常,智能指针也正常析构。这时大家肯就会有问题,为什么数据++的不正确?那么shared_ptr还是线程安全的吗?算。
【C++进阶】智能指针_第25张图片

循环引用

那么现在的shared_ptr就完整了吗?它还有没有什么问题?每次就是循环引用。
【C++进阶】智能指针_第26张图片
【C++进阶】智能指针_第27张图片
==我们可以看到最终对象没有被销毁。==那么没有循环引用呢?
【C++进阶】智能指针_第28张图片
==我们可以看到,没有循环引用时,对象被正常销毁。==那么该怎么解决这个问题呢?这时就用到了weak_ptr。

weak_ptr

weak_ptr的思想就是,只使用,不负责管理和释放。
【C++进阶】智能指针_第29张图片
【C++进阶】智能指针_第30张图片
【C++进阶】智能指针_第31张图片

删除器

删除器需要我们自己写一个仿函数,显示传给智能指针
【C++进阶】智能指针_第32张图片

【C++进阶】智能指针_第33张图片
这里实现的是unique_ptr的删除器,shared_ptr的删除器底层实现比较麻烦大家有兴趣可以自己去了解。

你可能感兴趣的:(C++初阶和高阶,c++,数据结构,java)