boost::shared_ptr和std::shared_ptr的共存问题

47

我希望在某个时候使用 boost::log,但是我无法将 std::shared_ptr 作为参数传递,因为编译器(VS2010)不能将其转换为 boost::shared_ptr

我不太喜欢它们彼此之间是外来的事实。

是否有一种安全和透明的方法将它们相互转换,以便它们不会互相干扰?

我不认为这是 这个问题 的重复,该问题指出两者是相同的。


有关 C++11 之前的答案,请参见:https://dev59.com/cmw15IYBdhLWcg3w6f80#6327305 - janm
我遇到了一个类似的问题,涉及std::array和boost::array。 - alfC
@alfC 我认为没有简单的方法可以在不复制数组内容的情况下在std::arrayboost::array之间进行转换。 - Marshall Clow
std::shared_ptrboost::shared_ptr(以及std::arrayboost::array)的情况下,也许可以使用reinterpret_cast吗? - alfC
3
即使这样可以让编译器停止报错,但这是破坏智能指针状态的一种可靠方式。 - Michael Burr
1
它们应该拥有相同的接口,为什么不黑入Boost,将boost/shared_ptr.hpp的内容替换为类似于#include <memory> namespace boost { using shared_ptr = std::shared_ptr这样的东西呢? - fghj
1个回答

74
你可以这样实现:
template<typename T>
boost::shared_ptr<T> make_shared_ptr(std::shared_ptr<T>& ptr)
{
    return boost::shared_ptr<T>(ptr.get(), [ptr](T*) mutable {ptr.reset();});
}

template<typename T>
std::shared_ptr<T> make_shared_ptr(boost::shared_ptr<T>& ptr)
{
    return std::shared_ptr<T>(ptr.get(), [ptr](T*) mutable {ptr.reset();});
}

编辑:请注意,这不能用于源指针的弱引用。因此,请小心使用!

2
构造函数的第二个参数到底是什么?从构造函数的签名来看,它似乎应该是一个删除器,但我不理解其语法。 - Chowlett
12
+1 真的很棒的技巧,使用捕获值的方式在删除器 Lambda 函数内部保留原始 ptr 的副本(因此也保留了一个额外的引用计数)。我必须承认,我花了一段时间来理解这个技巧。 - Christian Rau
5
boost::shared_ptr中的lambda删除器被存储为其成员,并且由于按值捕获,它又拥有了std::shared_ptr的副本作为成员,从而增加了原始对象的引用计数。因此,每个boost::shared_ptr通过其删除器成员增加了原始对象的引用计数。但是当boost::shared_ptr的引用计数(它实际上独立于std的引用计数)达到0时,什么也不会被删除,因为删除器是一个空操作,但是删除器的销毁实际上会减少原始引用计数。 - Christian Rau
6
这种方法有趣但存在缺陷。当所有强引用都超出作用域时,删除器会与计数器一起保持并执行。这种方法的问题在于,在存在weak_ptr的情况下,将调用删除器,但什么也不会发生。只要还有至少一个weak_ptr,对象的生命周期就会因删除器中的引用而被人为延长,从而破坏了weak_ptr/ shared_ptr组合的语义。修复很简单,设计很好,只需要改变实现方式:[ptr](T*){ptr.reset();} - David Rodríguez - dribeas
2
@ronag 现在的lambda函数需要加上mutable吗?(是的,刚刚确认过。) - dyp
显示剩余24条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接