最近为了学习 C++ 的智能指针,带着以下问题阅读了 C++ primer 里的智能指针章节,并记录问题的解答。
问题:
- 出现背景
- 智能指针的原理是什么
- 怎么使用
- 注意事项
- API 地址
1. 出现背景
程序使用动态内存的需求:
- 程序不知道自己需要多少对象
- 程序不知道对象的准确类型
- 程序需要在多个对象间共享数据
在之前的编程中,使用 C++ 的 new 关键字来动态分配堆里面的内存,并在某个时间段调用 delete 来释放分配的内存。但是很容易出现以下两种问题,从而导致程序异常:
- 忘记释放内存,这种情况会导致内存泄露。
- 释放内存之后又企图访问这块空间,导致非法引用内存。
为了更方便的管理动态分配的内存,C++ 提出了三种智能指针来辅助管理动态内存
- shared_ptr
- unique_ptr
- weak_ptr
从此告别裸指针,彻底解决内存相关问题。
2. 智能指针的原理是什么
shared_ptr 允许多个指针指向同一个对象,内部维护了一个“计数器”,
- 每增加一个 shared_ptr 指向同一对象,其内部“计数器”加1,
- 每减少一个 shared_ptr 指向同一对象,其内部“计数器”减1
当内部“计数器”为0时,即没有 shared_ptr 指向该对象,则该对象会被自动销毁。
unique_ptr 则“独占”所指向的对象。
类似与 shared_ptr,只是每个对象仅允许一个 unique_ptr 指向它。
weak_ptr 是一种弱引用,指向 shared_ptr 所管理的对象。
使用 weaked_ptr 指向对象不会增加 shared_ptr 的“计数器”,是一种“弱”引用,即不负责管理对象生命周期。
3. 怎么使用
- 使用 make_shared 来返回对象的 shared_ptr 指针。
- unique_ptr 只能通过构造函数来创建。
- shared_ptr 和 unique_ptr 都可以使用 (*p) 来解引用。
- 可以自定义分配内存的析构函数。
- weak_ptr 有一个 lock() 函数,可以用来返回它指向对象的 shared_ptr。
4. 注意事项
- shared_ptr 放在容器里,如果忘记 erase 对象,则会造成内存泄露。(这是唯一会造成内存泄露的方法)