智能指针

谁开发谁保护,谁污染谁治理——C++县政府宣

动态内存

在了解智能指针之前,先明确C++几种内存管理的形式:

  • 静态内存:用于保存局部static对象、类static数据成员及全局变量(使用前存在,程序结束时销毁)
  • 栈内存:用于保存局部非static对象(程序块运行时存在)
  • 动态内存:通过指针及new与delete管理的对象,位于堆上

动态内存隐患

由于通过动态内存获得的对象生命周期与创建位置无关,需要显式释放,因此使用new和delete进行动态内存存在下列两个隐患:

  • 内存泄漏:忘记释放内存
  • 野指针:尚有指针指向内存时,就释放了该内存,指针指向已经删除的对象或访问受限的内存区域的指针

智能指针

为了克服手动进行动态内存管理的弊端,我们引入了只能指针的概念,对动态内存进行自动管理,智能指针模板定义在memory头文件中。智能指针实际上是将普通指针封装成了栈对象。

智能指针的种类

shared_ptr

共享智能指针,多个智能指针指向相同对象,通过计数器实现记录指针的数目,一旦一个shared_ptr计数器变为0,自动释放该对象。

使用make_shared函数进行动态内存分配

该函数是一个模板函数,返回一个shared_ptr指针。

1
2
shared_ptr<int> p1 = make_shared<int>(45);  //p1->int(45)
auto p2 = p1;
graph LR
    node((p1))
    node1((p2))
    node2[45]
    node-->node2
    node1-->node2

下面的代码解释了shared_ptr自动管理内存的原理

1
2
3
4
5
auto r = make_shared<int>(45);
r = q; //给r赋值令其指向另一个地址
//递增q指向对象的引用计数器
//递减r指向对象的引用计数器
//r计数器清0,销毁r原先指向的对象

unique_ptr

不支持强拷贝与赋值,但一个unique_ptr如果快要被销毁了(临时右值),那么可以进行拷贝。

weak_ptr

智能指针的潜在风险

在讲解weak_ptr时,我们先看一下只能指针的潜在风险:当shared_ptr相互引用时,导致计数器永远无法清空,从而死锁,造成内存泄漏。

weak_ptr的作用

与shared_ptr配合使用,不改变引用计数器,当最后一个shared_ptr指针被释放,即使仍有weak_ptr,对象依然被销毁。所以该指针只是提供了一种访问对象的手段。weak_ptr可以检测到所管理的对象是否已经被释放,从而避免非法访问。

参考文献

0%