罗剑锋的 C++ 实战笔记
罗剑锋
前奇虎 360 技术专家,Nginx/OpenResty 开源项目贡献者
35514 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 32 讲
结束语 (1讲)
罗剑锋的 C++ 实战笔记
15
15
1.0x
00:00/00:00
登录|注册

08 | smart_ptr:智能指针到底“智能”在哪里?

思考题
注意事项
优势
智能指针的作用
shared_ptr
unique_ptr
智能指针

该思维导图由 AI 生成,仅供参考

你好,我是 Chrono。
上节课在讲 const 的时候,说到 const 可以修饰指针,不过今天我要告诉你:请忘记这种用法,在现代 C++ 中,绝对不要再使用“裸指针(naked pointer)”了,而是应该使用“智能指针(smart pointer)”。
你肯定或多或少听说过、用过智能指针,也可能看过实现源码,那么,你心里有没有一种疑惑,智能指针到底“智能”在哪里?难道它就是解决一切问题的“灵丹妙药”吗?
学完了今天的这节课,我想你就会有个明确的答案了。

什么是智能指针?

所谓的“智能指针”,当然是相对于“不智能指针”,也就是“裸指针”而言的。
所以,我们就先来看看裸指针,它有时候也被称为原始指针,或者直接简称为指针。
指针是源自 C 语言的概念,本质上是一个内存地址索引,代表了一小片内存区域(也可能会很大),能够直接读写内存。
因为它完全映射了计算机硬件,所以操作效率高,是 C/C++ 高效的根源。当然,这也是引起无数麻烦的根源。访问无效数据、指针越界,或者内存分配后没有及时释放,就会导致运行错误、内存泄漏、资源丢失等一系列严重的问题。
其他的编程语言,比如 Java、Go 就没有这方面的顾虑,因为它们内置了一个“垃圾回收”机制,会检测不再使用的内存,自动释放资源,让程序员不必为此费心。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

智能指针在现代C++中扮演着重要角色,通过代理裸指针,实现了资源的自动管理,避免了内存泄漏等问题。文章介绍了unique_ptr和shared_ptr两种常见类型的智能指针,分别适用于独占所有权和共享资源的场景。然而,过度使用shared_ptr可能会降低运行效率,引发循环引用和难以排查的错误。为了解决循环引用问题,文章提出了使用weak_ptr的建议。总的来说,本文深入浅出地介绍了智能指针的使用方法和注意事项,为读者提供了全面的了解和使用指南。通过学习本文,读者可以清晰地了解智能指针的“智能”之处,以及如何在实际项目中应用智能指针来提高代码的安全性和可维护性。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《罗剑锋的 C++ 实战笔记》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(62)

  • 最新
  • 精选
  • Eglinux
    C++ 这么小众吗?讲得这么好,如果写成书,完全可以看成另外一本 effective C++ 了,为什么才 3000 多订阅人数?

    作者回复: 已经不少了吧,相识就是缘分,笑。

    2020-05-23
    3
    50
  • 酸葡萄
    老师,您好,什么时候用weak_ptr,什么时候用shared_ptr?

    作者回复: 我给一个不是很精确的评价标准吧。 shared_ptr是强引用,无论如何都需要持有共享对象的时候就用它。 weak_ptr是弱引用,不一定要持有对象,只是“偶尔”想去看看对象在不在,不在也可以接受。

    2020-06-17
    29
  • eletarior
    默认用的比较多的是unique_ptr ,相反的shared_ptr倒是用的不多,因为担心文中提到的循环引用,资源消耗,线程安全等问题。大部分时候,unique_ptr是能完全取代裸指针的。如果是存粹的标准C++代码,使用智能指针确实很舒服,把它们当成一个普通的类型看就行了。但是,同时,作为C++程序员我们又不得不和裸指针打交道,不论是Linux还是Windows,我们不可避免的要使用它们的系统api,于是就不得不使用get将智能指针转成裸指针。而这条指针所指向的内存在系统api里也许是不应该随意析构掉的,因为在系统内部可能还得继续使用这段内存,那么在这种场景下,智能指针的特性就可能帮倒忙,难受了😫。针对这种问题,我想到的就是延长这个智能指针的生命周期,或者直接使用release将裸指针释放出来,可是这样一来,delete就少不了要使用了😔

    作者回复: 是的,涉及到系统底层,有时候就可能要用到delete,不过你也可以试着用RAII来管理,或者用shared_ptr的定制删除函数,还是能够找到不用delete的方式的。

    2020-05-25
    2
    20
  • 颓废人才
    罗老师您好,还有一个问题,常用的C++ reference 我看到一个 cplusplus.com和cppreference.com, 但是网上有一些不好评价,觉得这两个网站都有问题,罗老师这边一般参考的哪些文档网站,可以推荐下么。非常感谢。

    作者回复: 我一般看的是cppreference.com,觉得它的界面比较好,资料组织整理的也很清楚,和官方标准基本吻合。 这些网站都是免费的,我觉得就可以一起看,互相参照。

    2020-07-02
    2
    12
  • 禾桃
    “因为 shared_ptr 具有完整的“值语义”(即可以拷贝赋值)” 一直都觉得值语义这三个字比较难理解。想请教下这个概念到底是想说明什么问题,这个“值”该怎么理解?

    作者回复: 值是和引用对应的,值就是有实体,可以拷贝,而引用是虚的,只是个别名,操作上有区别。

    2020-05-25
    11
  • Luke
    使用智能指针可以自动析构“资源”,隐含了指针管理的细节,从而提高了代码的安全性和易用性,但是这是否同时意味着效率下降?在极致追求执行速度的系统中,是否需要避免使用智能指针,依赖程序员自己管理裸指针的new和delete呢?

    作者回复: 追求极致性能,那当然还是要自己管理好了,但这样也就要自己承担安全的责任了。 建议用unique_ptr,它的速度与裸指针几乎相同,没有引用计数的成本。

    2020-05-30
    6
  • 郭郭
    老师,关于unique_ptr,如auto ptr = ptr1,那ptr1就应该被置空啦。不需要显示的调用std::move

    作者回复: 我测试了一下,是不行的,会报编译错误,因为unique_ptr禁止了普通的拷贝赋值,只允许转移,必须调用std::move()。

    2020-05-24
    6
  • Geek_王
    罗老师能把文中提到的血泪教训详细说一下吗?什么问题?怎么解决的?

    作者回复: 就是类的析构函数比较大,里面的操作很多,用shared_ptr来管理,由于析构的时机不确定,经常会发生莫名其妙的系统抖动,就像是java/go的gc stop the world一样。

    2020-08-20
    3
    5
  • The Answer
    老师,shared_ptr 本身是线程安全的,但是如何理解它所管理的对象不是线程安全的呢?

    作者回复: shared_ptr就像是一个盒子,它自己是安全操作的,但一旦把里面的东西拿出来,就无法保证了。 shared_ptr和它指向的对象是彼此独立的,所以线程安全当然是没有关系的,shared_ptr只是一个handle,离开了handle,它就不能保证了。

    2020-07-12
    4
    5
  • Zivon
    罗老师,今天尝试使用智能指针改写双向链表的时候感觉实现很麻烦啊,请问在实现这种基本数据结构的时候需要使用智能指针吗

    作者回复: 基本的数据结构强调效率,用智能指针就有点成本略高,当然作为练手还是可以的。 智能指针最适合的应用场景是“自动资源管理”,链表还是不太合适,而且使用shared_ptr容易出现循环引用,改成weak_ptr会好一些。

    2020-05-26
    4
收起评论
显示
设置
留言
62
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部