您有两个课程Animal
和Dog
(其中Dog
继承自Animal
),您有一种情况,您经常期待一只动物,但正在发送一个一只狗的例子。在我的特定情况下,我经常向一个期待动物的函数(std::shared_ptr<Dog>
)强加一个强指针(std::shared_ptr<Animal>
)。
如果我们接受我们可以将函数参数作为引用(std::shared_ptr<Animal>&
,避免因为担心使用线程更改所有权而不应该将强指针作为引用参数的参数,我假设我们会使用std::shared_ptr<Dog> dog
投射reinterpret_cast<std::shared_ptr<Animal>&>(dog)
是安全的记忆吗?对吗?
如果是这样,除了线程问题之外还会出现什么问题;例如参考计数种类的那些?
要明确的是,目的是要有一个可以在许多情况下使用的解决方案,其中一次铸造并不是一个可行的解决方案。更重要的是,有许多对象必须被投射。此外,忽略std::unique_ptr
可能是也可能不是更好的解决方案。
添加最终要求 - 使用普通指针不允许我在虚拟的通用序列化器类函数的情况下更改原始std::shared_ptr
,因此无法模板化。
答案 0 :(得分:2)
由于无法直接在static_cast
上使用const_cast
,dynamic_cast
,reinterpret_cast
和std::shared_ptr
来检索与所传递的指针共享所有权的指针作为参数,应使用std::static_pointer_cast
,std::const_pointer_cast
,std::dynamic_pointer_cast
和std::reinterpret_pointer_cast
函数。
std::reinterpret_pointer_cast
在C ++ 11和C ++ 14中不可用,因为它仅由N3920提出并被《图书馆基础知识》 TS in February 2014所采用。但是,它可以实现如下:
template <typename To, typename From>
inline std::shared_ptr<To> reinterpret_pointer_cast(
std::shared_ptr<From> const & ptr) noexcept
{ return std::shared_ptr<To>(ptr, reinterpret_cast<To *>(ptr.get())); }
答案 1 :(得分:0)
我经常向一个动物期待函数(
std::shared_ptr<Dog>
)投射一个强指针(std::shared_ptr<Animal>
)。
无需强制转换(即显式转换)。派生类型的共享指针可以隐式转换(1)到指向基类的共享指针。
(a)如果我们接受我们可以将函数参数作为参考
如果满足一些要求,我们只能接受这种假设。首先,函数不能将引用的参数存储在函数范围之外(复制除外)。其次,作为引用传递的指针必须是本地的或临时的 - 或者如果不是,那么该函数不能调用任何可以直接或间接访问引用指针的函数。
还要考虑如果引用是非const的,那么就不能依赖隐式转换(1)。相反,您必须创建一个单独的正确类型的共享指针(您可以使用隐式转换来创建它并传递它。一个const引用参数,或一个非引用参数没有这个问题。
(b)我假设使用
reinterpret_cast<std::shared_ptr<Animal>&>(dog)
施放std :: shared_ptr狗是安全的记忆,对吧?
标准方面,您建议的演员阵容不安全 - 它有未定义的行为。我不会从假设(a)中看出假设(b)是如何得出的。
如果在您的情况下使用对shared_ptr的引用作为参数可以,但是您无法避免由于转换而导致的refcounter的递增/递减(派生到base,非const到const),我建议使用反而是参数的裸指针。