智能指针
本文最后更新于:November 29, 2024 pm
万众瞩目的C++11终于引入了全新的基于RAII
的三个智能指针类——std::unique_ptr
,std:: shared_ptr
和std::weak_ptr
此系列博客将会一一介绍三种类,使用注意事项,以及关于Pimpl
的编程原则
裸指针的问题
使用过C
的朋友对指针肯定不陌生,在C
中,指针提供了对机器底层的访问接口,这也使得C
和其它语言在内存访问上有比较大的不同。
如果在C++
中继续使用C
风格的裸指针进行动态资源的管理,就会暴露出很多很多问题:
在声明一个裸指针时,并没有明确它应该指向一个单独的对象,还是一个数组,除非在变量名上显式写出
在声明裸指针时,没有提示是否应该在使用完成之后就立刻将之释放掉
即使我们知道了应该将之释放,我们也不知道应该如何操作,我们是应该使用`delete`操作符,还是应该调用一个专门的函数?
即使知道了应该使用`delete`操作符,那么是`delete`还是`delete[]`?错误调用会导致未定义行为
即使能确信,指针拥有其管理的对象,并且我们应该执行析构操作,但是要保证析构路上的所有代码都执行且只执行1次,仍然比较困难。未执行会导致资源回收失败,多此执行则会导致未定义行为
没有什么正确的方式能够检测出指针是否是悬空的(dangle),也就是说无法断定其指向的内存是否已经被回收过了
虽然裸指针是一种强力的工具,近几十年的经验发现,只要在工程上稍微疏忽一下,裸指针就可以把人搞得晕头转向。
智能指针(Smart Pointer)是解决上述问题的一种方案之一。智能指针对裸指针进行了封装,它们的行为也被重载和包装得很像裸指针,但是规避了很多使用裸指针面临的风险。因此,学习了智能指针之后,在今后使用C++
时,都应该优先选用智能指针,毕竟智能指针能做到几乎任何裸指针能做到的,但是犯错的几率会大大减少,但也只是减少。
C++11中一共有四种智能指针,std::auto_ptr
, std::unique_ptr
, std::shared_ptr
, std::weak_ptr
,它们都是为了管理动态资源而被设计出来的。具体地,它们保证动态对象在适当的时机以适当的方式析构(包括出现异常时),来防止资源泄露。
其中,std::auto_ptr
是一个从C++98中残留下来的弃用特性,其自身在功能实现上,需要借助移动语义,但这是C++98并不具备的,所以通过拷贝的方式来做了变通,给人一种不伦不类的感觉。在C++11之后,其已经被std::unique_ptr
取代,并且后者的能力更强。
为什么要强调动态资源/动态对象?因为博主在知乎等平台上看到一些数落C++智能指针缺陷的人,有些人会往智能指针里扔一个栈上的地址,等栈被弹出之后来一句,现在内存不安全了。有时这种回答的排名还很靠前,具有很强的误导性。
1 |
|
系列导航
Item18:使用std::unique_ptr来管理具备专属所有权的资源
Item19:使用std::shared_ptr来管理具备共享管理权的资源
Item20:对于类似std::shared_ptr但是可能空悬的指针,应当使用std::weak_ptr
Item21:优先使用std::make_unique和std::make_shared
Item22:使用Pimpl时,将特殊成员函数的定义放到实现文件中
注
内容出自对于 Effective Modern C++[1] Item18~22的学习笔记,并依照原文顺序组织
- Effective Modern C++ by Scott Meyers(O’Reilly). Copyright 2015 Scott Meyers, 978-1-491-90399-5 ↩
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!