以我为例 T
是pcl::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 forboost::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 );
}
注意第二个参数是按值。这一下子解开了这个谜团:
#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/