关于 GC 和 shared_ptr 的讨论

C++ 的世界里被人憎恨的就是 new 之后的 delete,为此 C++98 引入了 auto_ptr 却因为语义的含糊造成使用上的困难没有得到广泛的应用,为此 boost 的 smart_ptr 提供了一些语义上更加明确的智能指针,RAII 的应用是 C++ 不同于 Java 的一个重要的特点,如 smart pointer 不仅管理对象的生存周期还可以管理资源,C++ 确保异常抛出后对象的析构函数一定会被调用,这样智能指针就可以释放内存、释放其他的资源了。Java 并没有类似的概念,仅仅靠 GC 只能解决内存的释放,却无法解决其他资源的问题,为此 Java 有一个习惯的 pattern(结合关键字 finally),而 C++ 却没有提供 finally。在 JDK 7 里面甚至提供了 Closable 接口和 try with resource 这种形式(参看这里)。

那么 shared_ptr 和 GC 各自有些什么优缺点呢?

  • shared_ptr 管理对象可以较快的释放内存,而 GC 往往需要等待到一个合适的时候
  • 因为 shared_ptr 管理的内存块一般较小比较容易造成内存碎片化,GC 批量释放内存后往往可以重新整理一下内存(mark and compact),碎片化的可能性较小
  • shared_ptr 是基于 reference counting 的,也就是说为每个对象关联了一个计数器用来 track 多少个 shared_ptr 指向它,这在存在循环依赖关系的时候会出现问题:类 A 和 B 都有一个 share_ptr 指向对方,即便指向他们两个对象外部的 shared_ptr 已经消亡,其内部的 shared_ptr 仍然存在,因此导致一直无法释放;GC 的常见策略 mark and sweep 工作原理大致是首先将所有对象标记为没有使用(占用了额外的存储?),然后从 stack 中的对象开始根据对象的关系寻找更多具有引用的对象,将这些对象标记为被使用,最后重新遍历所有的对象,将未使用的清除掉,这个过程本身比较耗时,同时也会导致 stop the world
  • C++11 已经提供了基本 GC 的 ABI(参看这里),但是无法支持 mark and compact 这类移动对象的 GC(C++ 的指针的值会因此变化)
  • 搞 GC 的人总会吹捧 GC,比如这人… 但是其实使用 smarter pointer 并不是意味着所有的地方都需要用,更多的地方感觉使用引用就行了

anyway 程序员一般都是控制狂,越低级的控制欲越大,GC 怕是这些人的眼中钉咯

——————
And the LORD said unto Jacob, Return unto the land of thy fathers, and to thy kindred; and I will be with thee.

Advertisements
关于 GC 和 shared_ptr 的讨论

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s