谁开发谁保护,谁污染谁治理——C++县政府宣
动态内存
在了解智能指针之前,先明确C++几种内存管理的形式:
- 静态内存:用于保存局部static对象、类static数据成员及全局变量(使用前存在,程序结束时销毁)
- 栈内存:用于保存局部非static对象(程序块运行时存在)
- 动态内存:通过指针及new与delete管理的对象,位于堆上
动态内存隐患
由于通过动态内存获得的对象生命周期与创建位置无关,需要显式释放,因此使用new和delete进行动态内存存在下列两个隐患:
- 内存泄漏:忘记释放内存
- 野指针:尚有指针指向内存时,就释放了该内存,指针指向已经删除的对象或访问受限的内存区域的指针
智能指针
为了克服手动进行动态内存管理的弊端,我们引入了只能指针的概念,对动态内存进行自动管理,智能指针模板定义在memory头文件中。智能指针实际上是将普通指针封装成了栈对象。
智能指针的种类
shared_ptr
共享智能指针,多个智能指针指向相同对象,通过计数器实现记录指针的数目,一旦一个shared_ptr计数器变为0,自动释放该对象。
使用make_shared函数进行动态内存分配
该函数是一个模板函数,返回一个shared_ptr指针。
1 | shared_ptr<int> p1 = make_shared<int>(45); //p1->int(45) |
graph LR node((p1)) node1((p2)) node2[45] node-->node2 node1-->node2
下面的代码解释了shared_ptr自动管理内存的原理
1 | auto r = make_shared<int>(45); |
unique_ptr
不支持强拷贝与赋值,但一个unique_ptr如果快要被销毁了(临时右值),那么可以进行拷贝。
weak_ptr
智能指针的潜在风险
在讲解weak_ptr时,我们先看一下只能指针的潜在风险:当shared_ptr相互引用时,导致计数器永远无法清空,从而死锁,造成内存泄漏。
weak_ptr的作用
与shared_ptr配合使用,不改变引用计数器,当最后一个shared_ptr指针被释放,即使仍有weak_ptr,对象依然被销毁。所以该指针只是提供了一种访问对象的手段。weak_ptr可以检测到所管理的对象是否已经被释放,从而避免非法访问。
参考文献
- 1.C++ primer ↩