shared_ptr和切片

时间:2010-07-22 04:19:50

标签: c++ shared-ptr

我曾与之合作的人曾说过,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*

暗示在这些环境中使用是安全的,但他似乎并不这么认为。

2 个答案:

答案 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