在我的情况下,
问题在于
尽管上述代码将
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
类型的一部分而不是cv限定符。以下代码可行。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<const T>
到 boost::shared_ptr<T>
?这应该是可能的,因为通过 const T*
安全地查看 T
,但我无法想出一种方法。
r
,那么它总是需要至少一次复制或移动,并且转换为 const 会添加一个移动但不会额外复制。这些模板没有设计为按引用传递r
,难道是出于线程安全的考虑吗? - patatahooliganshared_ptr
就是解引用和原子递增(或两者都有)。此外,如果r
是一个引用,那么用户代码可能会使p
和r
成为完全相同的shared_ptr
,我不知道这会产生什么后果。使用复制交换更简单、更安全。 - ratchet freak*p
中。锁定将被两种方式所需,因为它是一个原子存储。就像我之前说的那样,转换为 const 将添加一个单独的移动,因为shared_ptr<const T>
将是一个临时的。所以我认为这个答案及其评论已经回答了这个问题。 - patatahooligan