我曾与之合作的人曾说过,shared_ptr是不安全的,并且会在从派生类转换为基类时进行切片(即向上转换)。例如,如果有两个A和B类,其中B来自A,那么
shared_ptr<A> a(new B)
会切片。我指着他http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm 在哪里说
只要shared_ptr<T>
可以隐式转换为shared_ptr<U>
,
T*
就可以隐式转换为U*
。
暗示在这些环境中使用是安全的,但他似乎并不这么认为。
答案 0 :(得分:12)
有人错了,object slicing不适用于指针。指针用法被包裹在shared_ptr
中并没有改变它 - 它在这里没有做任何特殊的魔法,它用传递给它的构造函数的值初始化一个内部指针。
简化它可能看起来像这样就是为了这个问题的目的:
template<class T> struct ptr {
T* t;
ptr(T* t) : t(t) {}
// ...
};
您丢失了B
的静态类型信息,是的,但是对于指向的对象没有任何变化。
答案 1 :(得分:-1)
指针是POD(仅供记录:shared_ptr
s不是。)
问题引用:
每当T *可以隐式转换为U *时,shared_ptr可以隐式转换为shared_ptr。
这是关于从一种类型转换为另一种类型,这与向上转换不同。 shared_ptr<A>
与shared_ptr<B>
之间没有继承关系,无论A
来自B
还是反之亦然。这就是shared_ptr
对象本身没有切片的原因。
考虑一个没有虚拟析构函数的类层次结构A,B。
std::shared_ptr<A> a(new B);
auto a = std::make_shared<B>();
将捕获B&#39的解除分配器,然后在需要时调用B&#39的析构函数
std::shared_ptr<A> a((A*)(new B));
不会做这样的事情,并会导致指向对象的切片问题。
例如,使用unique_ptr
具有不同的行为:
std::unique_ptr<A> a(new B);
std::unique_ptr<A> a((A*)(new B));
会出现切片问题,而
auto a = std::make_unique<B>();
赢得&#39;吨
使用普通指针不会有任何帮助:
A* a = new B{};
delete a;
是灾难的秘诀。
可用的示例代码here。