使用shared_ptr的开销和实现

Goo*_*ofy 13 c++ shared-ptr c++11

简短介绍:我正在研究多线程代码,我必须在两个线程之间共享动态分配的对象.为了使我的代码更清晰(并且更不容易出错),我希望在每个线程中明确地"删除"对象,这就是我想要使用的原因shared_ptr.

第一个问题:

我想知道在运行时是否实现-> operatorin shared_ptr有一些额外的开销(例如更大unique_ptr).我正在谈论的对象通常是在创建之后仅复制一次的longlife实例(当我在线程之间分发它们时),然后我只访问这些对象的方法和字段.

我知道,shared_ptr这只保护引用计数.

第二个问题:

shared_ptr在libstdc ++中如何优化?它总是使用互斥量还是利用原子操作(我专注于x86和ARM平台)?

Mat*_* M. 14

第一个问题:使用operator->

我看到的所有实现都T*shared_ptr<T>类中具有正确的本地缓存,因此该字段位于堆栈上,operator->因此具有与使用本地堆栈相当的成本T*:根本没有开销.

第二个问题:互斥/原子

我希望libstdc ++能够在x86平台上使用原子,无论是通过标准工具还是特定的g ++内在函数(在旧版本中).我相信Boost实现已经这样做了.

但是,我不能对ARM发表评论.

注意:C++ 11引入了移动语义,在使用中自然会避免许多副本shared_ptr.

注意:阅读关于shared_ptr 这里的正确用法,你可以使用引用shared_ptr(const或不使用)来避免大多数副本/破坏,所以那些性能并不太重要.

  • @Goofy:不,使用`make_shared`你没有明确地执行`new`,另一方面你需要显式传递创建对象的类型; 暂时不需要调用`move`.因此它产生:`Foo :: Foo():num(std :: make_shared <int>(30)){}` (2认同)

Jon*_*ely 13

GCC的shared_ptr将在单线程代码中不使用锁定或原子.在多线程代码中,如果CPU支持原子比较和交换指令,它将使用原子操作,否则引用计数受互斥锁保护.在i486及更高版本上它使用原子,i386不支持cmpxchg,因此使用基于互斥锁的实现.我相信ARM使用原子技术用于ARMv7架构以及稍后的版本.

(这同样适用于std::shared_ptrstd::tr1::shared_ptr.)

  • 没有`#define`.Libstdc ++使用的函数根据程序是否链接到"libpthread"而(在运行时)调度到原子实现或非原子实现.如果它链接到`libpthread`,则假定存在多个线程并使用原子impl.如果没有链接到`libpthread`那么程序是单线程的,因此使用非原子impl. (6认同)
  • @Jonathan Wakely是libstdc ++的实现者之一.虽然,如果你能详细说明一下,我会觉得很好,比如什么是定义,什么是默认? (2认同)
  • 在"选择锁定政策"部分的http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr上有一些简要的文档 (2认同)