关于C++智能指针的一次重要对话

问题引入

【提问者】:请教大家一个问题。我把一个对象做成了共享指针std::shared_ptr,但是有一个库需要裸指针。这种情况下,我通过get方法,获得裸指针给这个库的函数使用,这样行不行?有什么需要注意的问题吗
【程序喵】:行,保证裸指针在shared_ptr生命周期内就没事
【提问者】:是啊,我也是怕这个。共享指针认为,应该把指针干掉了,但是那个裸指针还在被用。但是shared_ptr本来就会遇到这种问题,这个是开发人员自己需要处理的情况,是吧?也就是说,我这么写,也算是业界认可的方法,是吧?
【程序喵】:需要自己处理。反正我有时候这样写,业界认不认可咱不知道。
【钱能】:按范式,有些编程真当不需要像太空人的服装那样又笨又重,C++编程就是能很好地平衡性能与安全与优雅的关系。

问题讨论

大家都有共识,get方法获取裸指针的方式可以,但是危险是摆在那里的。但是需求摆在那里:

可是我这个库里就是要传裸指针啊,这该怎么办呢?

【钱能】:偶尔用一下,可以。编程中偏、怪、繁,甚至挑战安全性的代码不可避免,但是要注释,要最少化。这是为了保证主体范式编程的需要,而做出的牺牲。

问题升华

【tom】: weak_ptr官方文档 引入weak_ptr的意义
【tom】:

  • 如果你用裸指针,有点经验的人会马上小心行事,问前问后了解相关代码。如果你用智能指针,了解的人会放心,不太用管别的代码。如果语法上用了智能指针,实际用的指针,就好比把三轮车裹上塑料布,载客上高速…
  • weak_pointer的出现就是因为应对这种情况。
  • 智能指针先默认unique 不要shared. unique禁止copy,会让你编译错误,这时候你再想想,是move还是改shared. 很多时候unique能更安全的解决问题.

【提问者】:既然大佬都出现了,我就再问一下吧。我觉得unique用在这种场景下好像是有点问题的,比如我现在有一堆图层对象,把他放到map中,map统一管理。然后还需要把图层对象的裸指针传给库函数用。这种情况下,就不好用unique了吧。如果给出去了,map中就没有了。这种情况是不是就是您说的,需要改成shared了?

【tom】:

  • 我的话,正是用unique的时候。我来分配内存,我来回收,中间给库用(假设库只是使用,而且是指针)。Shared总是集体行动,批量使用,共享“所有权”。网络应用比如ASIO是Shared的最佳场景,因为这种应用本身,就是在“共享”内存所有权。unique应用是“传递”内存所有权。你这个应用,甚至不涉及所有权,只是“使用权”,把逻辑整理好,保证unique的生命周期涵盖库函数的加载周期就行了。

  • 保证map的生命周期大于库函数,如果不需要某个内存,删掉元素,内存也回收了。

  • 关键是有效区分所有权和使用权,然后决定有几个所有权。

推荐阅读

  1. 为何优先选用unique_ptr而不是裸指针?
posted @ 2022-05-25 19:30  时间的风景  阅读(24)  评论(0编辑  收藏  举报