霍华德(Howard)已经很好地回答了这个问题,尼科尔(Nicol)就使用单一标准共享指针类型(而不是许多不兼容的指针类型)的好处提出了一些好的意见。
尽管我完全同意委员会的决定,但我确实认为在特殊情况下使用非同步shared_ptr
类型会有所益处,因此我已经对该主题进行了几次调查。
如果我不使用多个线程,或者如果我使用多个线程但不跨线程共享指针所有权,那么原子智能指针就显得过分了。
使用GCC时,如果程序不使用多个线程,则shared_ptr不会将原子操作用于引用计数。这是通过包装器功能更新引用计数来完成的,该包装器功能可检测程序是否为多线程(在GNU / Linux上,只需检测程序是否链接至即可完成libpthread.so
),并相应地分派给原子或非原子操作。
我早在多年前就意识到,由于GCCshared_ptr<T>
是根据__shared_ptr<T, _LockPolicy>
基类实现的,因此即使显式使用,即使在多线程代码中,也可以将基类与单线程锁定策略一起使用__shared_ptr<T, __gnu_cxx::_S_single>
。不幸的是,由于这不是预期的用例,因此在GCC 4.9之前并不能很好地发挥作用,并且即使您明确请求了该_S_single
策略,某些操作仍然使用包装函数,因此仍分派给原子操作。请参阅第(2)点,网址为http://gcc.gnu.org/ml/libstdc++/2007-10/msg00180.html以获得更多详细信息和GCC补丁,以允许甚至在多线程应用中也使用非原子实现。我坐在那个补丁上已经有好几年了,但是我最终在GCC 4.9上提交了它,它允许您使用这样的别名模板来定义不是线程安全的共享指针类型,但是速度稍快一些:
template<typename T>
using shared_ptr_unsynchronized = std::__shared_ptr<T, __gnu_cxx::_S_single>;
此类型不能与之互操作,std::shared_ptr<T>
并且只有在保证shared_ptr_unsynchronized
没有其他用户提供的同步就永远不会在线程之间共享对象时,才可以安全使用该类型。
当然,这是完全不可携带的,但是有时候可以。如果shared_ptr_unsynchronized<T>
是的别名shared_ptr<T>
,那么使用正确的预处理器技巧,您的代码将仍然可以与其他实现一起正常工作,对于GCC来说,它会更快一点。
如果您在4.9之前使用的是GCC,则可以通过在_Sp_counted_base<_S_single>
您自己的代码中添加显式的特殊化(并确保没有人在__shared_ptr<T, _S_single>
不包含特殊化的情况下进行实例化,以避免发生ODR冲突)来使用该std
类型。可以在实践中工作,因为在这种情况下,我将专长添加到GCC还是将专长添加到自己的代码之间没有区别。