c++ - 如何将 boost::atomic_store 与 shared_ptr<T> 和 shared_ptr<const T> 一起使用?

标签 c++ boost shared-ptr atomic

以我为例 Tpcl::PointCloud<pcl::PointXYZ>>但问题应该代表任何类型 T .以下示例会产生错误:

using pc = pcl::PointCloud<pcl::PointXYZ> >;
boost::shared_ptr<pc> p(new pc);
boost::shared_ptr<const pc> const_p(new pc);

// This is legal
const_p = p;

// The atomic equivalent is not
boost::atomic_store(&const_p, p);

问题是 boost::atomic_store期望两个参数都是 T*T , 但这些被认为是不同的类型,尽管分配 p 是完全安全的。至 const_p .以下内容也不起作用。

boost::atomic_store(&const_p, const_cast<boost::shared_ptr<const pc> > (p));

尽管上面基本上类型转换了一个pc*const pc*这是非常安全的,它会产生关于 const_cast 的错误无法转换为不同的类型。我明白是因为pc是一个模板参数,它被认为是 shared_ptr 类型的一部分而不是简历资格。后续工作

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p));

但是,它会产生额外的不必要的 boost::shared_ptr .据我了解,boost::const_pointer_cast<const pc>(p) 也是如此。这可以避免,如果 p不再需要。

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(std::move(p));

这仍然会创建一个额外的对象,但这无关紧要,因为引用计数没有被修改,这是复制 shared_ptr 的昂贵部分。由于是原子的。

碰巧这发生在我代码的非关键部分,所以我对上面的内容没问题,但我想知道以供将来引用:如果 std::move不是一种选择,一个人如何自动存储 boost::shared_ptr<T>boost::shared_ptr<const T>没有创建不必要的临时指针的开销?这应该是可能的,因为查看 T 是安全的通过 const T* ,但我想不出办法。

最佳答案

I understand that because pc is a template argument, it is considered part of the type of the shared_ptr and not a cv qualification.

是的,这就是所谓的“不可推导上下文”。

The following work

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p));

However, it creates an extra unecessary boost::shared_ptr. It is my understanding that the same is true for boost::const_pointer_cast<const pc>(p) This can be avoided if p is no longer needed.

好吧,惊喜,你总能得到拷贝:

template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
    boost::detail::spinlock_pool<2>::scoped_lock lock( p );
    p->swap( r );
}

注意第二个参数是按值。这一下子解开了这个谜团:

Live On Coliru

#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 
#include <boost/atomic.hpp>

namespace pcl {
    struct PointXYZ {};
    template <typename P> struct PointCloud {
    };
}

int main() {
    using pc = pcl::PointCloud<pcl::PointXYZ>;
    boost::shared_ptr<pc> p             = boost::make_shared<pc>();
    boost::shared_ptr<const pc> const_p = boost::make_shared<pc>();

    // This is legal
    const_p = p;

    // The atomic equivalent is too
    boost::atomic_store<pc const>(&const_p, p);
}

If std::move was not an option, how would one atomically store a boost::shared_ptr to a boost::shared_ptr without the overhead of creating an unecessary temporary pointer?

你不能。这样看:加载/存储意味着是适合原子无锁实现的微不足道的操作。他们只做一件事,而且做得很好¹。

进行隐式转换不是该函数的职责。

我建议使用包装函数,甚至使用 ADL 从您自己的命名空间解决您自己的重载。

关于c++ - 如何将 boost::atomic_store 与 shared_ptr<T> 和 shared_ptr<const T> 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46155203/

相关文章:

c++ - 你能在 C++ 中使用 'new' 模拟动态数组大小吗?

c++ - 使用 MPFR 时如何在 Boost Multi precision 中设置舍入模式

c++ - boost 文件系统 directory_iterator 的非确定性执行

c++ - Pimpl 习语和没有友元声明的内部对象协作

c++ - 如何在 C++ 中使用类型名?

c++ - 媒体基金会水槽作家

C++ Trie字典——丢了两天

c++ - 简单更新索引的循环队列

c++ - 如何以更好的性能传递和共享 shared_ptr 所有权?

c++ - 通过 make_shared 用 shared_ptr 包装动态数组