c++是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)?

2021-12-14 16:25发布

std::unique_ptr:

1 小巧、高速、具备只移型别的智能指针,对托管资源实施专属所有权语义。

2 默认地,资源析构采用delete运算符来实现,但可以指定自定义删除器。有状态的删除器和采用函数指针实现的删除器会增加std::unique_ptr型别的对象尺寸

3 将std::unique_ptr 转换成std::sharedptr是容易实现的

std::shared_ptr:

1 提供方便的手段,实现了任意资源在共享所有权语义下进行生命周期管理的垃圾回收

2 与std::unique_ptr 相比,std::shared_ptr的尺寸通常是裸指针尺寸的两倍,它还会带来控制块的开销,并要求原子化的引用计数操作

3 默认的资源析构通过delete运算符进行,但同时也支持定制删除器。删除器的型别对std::shared_ptr的型别没有影响

4 避免使用裸指针型别的变量来创建 std::shared_ptr 指针

std::weak_ptr:

1 使用std::weakptr 来代替可能空悬的std::shared_ptr

2 std::weak_ptr 可能的用武之地包括缓存,观察者列表,以及避免std::shared_ptr 指针环路。

看看大师的总结,完美!!

具体到完全代替裸指针,恐怕也要再掂量掂量。

下面写一些劣势

std::shared_ptr 会增加内存开销,复制的时候cpu消耗提高【原子count操作】

std::unique_ptr 内存占用小,几乎可以媲美裸指针;但是它毕竟是一个类,使用的时候,不能复制,导致你一个作用域内只能有一个可用的实例【类似rust的所有权吧,你用起来有点束手束脚】;

std::weak_ptr 必须跟std::shared_ptr配合使用。

优势:

省去你自己判断啥时候该释放资源【异步回调时候智能指针可以完美避免手动控制生命周期;enable_shared_frome_this 已经可以算是一种特别的编程技巧了

媲美裸指针的操作习惯

解放了双手,C++跟脚本的代码越来越像了。

补充一下【之前审题不太好】

1.对于性能和内存使用有严格要求的场景,不要过于依赖智能指针。【比如嵌入式这些的,实际上C+class就够了】

2.对于类型不敏感的数据【也就是内存了】,可以考虑使用std::array或者std::vector等。因为这个时候,你实际上就是C的操作,类型对于该内存仅仅起到一个布局描述的作用,频繁的类型转换【非继承关系】、字段偏移等操作,用智能指针也没有什么好处【因为你还是会拿到裸指针去操作】

3.其他的对类型敏感,或者对作用域敏感的数据内存,可以都考虑使用智能指针。局部作用域使用 ,uniqe—ptr多作用域的使用shared_ptr,缓存可能失效的情况下使用weak-ptr。

我做一般应用的时候,除了容器,几乎一上来全部使用uniqe-ptr当需要抛出一个副本的时候,使用shared_ptr。当功能完成的时候,哪个内存是全局生命周期,改成裸指针【全局裸指针我都不判空】。如果该项目不是那么重要,甚至我都会全部用shared_ptr,不用关心性能问题,因为C++本身的编译性能已经很高了,随便写写性能就够了,只要不飞,内存泄漏不是问题。

当我要去判断某一个内存之后的操作会失效,但是不知道什么时候失效的时候,我使用weak_ptr和shared_ptr。通过weak_ptr接口可以线程安全的获取我之前的智能指针是否还生效。【这个时候,裸指针,几乎是没有办法的了,很容易出现野指针】