tjh*_*nce 7 c++ multithreading shared-ptr
std::shared_ptr
保证是线程安全的.我不知道典型实现使用什么机制来确保这一点,但肯定它必须有一些开销.即使您的应用程序是单线程的,也会出现这种开销.
以上情况如何?如果是这样,那是否意味着它违反了"你不为不使用的东西付费"的原则,如果你没有使用线程安全保证?
如果我们查看std :: shared_ptr的cppreference页面,他们在Implementation notes部分中声明了以下内容:
为了满足线程安全要求,引用计数器通常使用带有std :: memory_order_relaxed的std :: atomic :: fetch_add递增和递减.
有趣的是要注意实际的实现,例如libstdc ++实现文档在这里说:
对于libstdc ++中的shared_ptr版本,编译器和库是固定的,这使得事情变得更加简单:我们有一个原子CAS或者我们没有,请参阅下面的锁定策略以获取详细信息.
该选择锁定策略部分说(重点煤矿):
有一个_Sp_counted_base类,它是在枚举__gnu_cxx :: _ Lock_policy上参数化的模板.整个类系列在锁定策略上进行参数化,直到__shared_ptr,__ weak_ptr和__enable_shared_from_this.实际的std :: shared_ptr类继承自__shared_ptr,并根据libstdc ++配置的线程模型和平台自动选择锁定策略参数,以便使用最佳可用模板特化.这种设计是必要的,因为即使它具有默认值,shared_ptr也不符合额外的模板参数.可用的政策是:
[...]
3._S_Single
此策略使用不可重入的add_ref_lock()而不进行锁定.在没有--enable-threads的情况下构建libstdc ++时使用它.
并进一步说(强调我的):
对于所有三个策略,引用计数增量和减量是通过ext/atomicity.h中的函数完成的,它们检测程序是否是多线程的.如果程序中只存在一个执行线程,则使用较便宜的非原子操作.
因此,至少在此实现中,您不需要为不使用的内容付费.
至少在 i386 上的 boost 代码中,boost::shared_ptr
是使用原子 CAS 操作实现的。这意味着虽然它有一些开销,但它相当低。我希望 的任何实现都是std::shared_ptr
类似的。
在高性能数字代码的紧密循环中,我发现通过切换到原始指针并非常小心,可以提高一些速度。但对于普通代码 - 我不会担心它。