简体   繁体   English

shared_ptr和切片

[英]shared_ptr and slicing

Someone I worked with once said that shared_ptr was unsafe and would slice when casting from a derived class to a base class (ie upcasting). 我曾与之合作的人曾说过,shared_ptr是不安全的,并且会在从派生类转换为基类时进行切片(即向上转换)。 For example if there were 2 classes A and B where B derived from A, then 例如,如果有两个A和B类,其中B来自A,那么

shared_ptr<A> a(new B)

would slice. 会切片。 I pointed him to http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm where it says 我把他指向http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/shared_ptr.htm

shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T* can be implicitly converted to U* . 只要T*可以隐式转换为U* shared_ptr<T>就可以隐式转换为shared_ptr<U>

implied that it's safe to use in those contexts but he didn't seem to think so. 暗示在这些情况下使用是安全的,但他似乎并不这么认为。

That someone is wrong, object slicing doesn't apply to pointers. 有人错了, 对象切片不适用于指针。 That the pointer usage is wrapped away in a shared_ptr doesn't change that - it doesn't do any particular magic here, it initializes an internal pointer with the value passed to its constructor. 指针用法被包装在shared_ptr并没有改变它 - 它在这里没有做任何特殊的魔法,它用传递给它的构造函数的值初始化一个内部指针。

Simplified it could look eg like this for the purpose of this question: 为了这个问题,简化它可能看起来像这样:

template<class T> struct ptr {
    T* t;
    ptr(T* t) : t(t) {}
    // ...
};

You lose the static type-information of B , yes, but nothing changes regarding the object pointed to. 你丢失了B的静态类型信息,是的,但是对于指向的对象没有任何变化。

It is true that object slicing doesn't apply to pointers 确实,对象切片不适用于指针

Pointers are PODs (just for the record: shared_ptr s aren't). 指针是POD(仅用于记录: shared_ptr不是)。

The question quotes: 问题引用:

shared_ptr can be implicitly converted to shared_ptr whenever T* can be implicitly converted to U*. 只要T *可以隐式转换为U *,shared_ptr就可以隐式转换为shared_ptr。

This is about converting from one type to another, which is different from upcasting. 这是关于从一种类型转换到另一种类型,这与向上转换不同。 There's no inheritance relationship between shared_ptr<A> and shared_ptr<B> , whether or not A derives from B or viceversa. shared_ptr<A>shared_ptr<B>之间没有继承关系,无论A是否来自B或反之亦然。 This is the reason why the shared_ptr object itself doesn't slice. 这就是为什么shared_ptr对象本身不切片的原因。

It is not true that object slicing cannot be a concern 对象切片不是一个问题,这是不正确的

Consider a class hierarchy A, B with no virtual destructors. 考虑没有虚拟析构函数的类层次结构A,B。

std::shared_ptr<A> a(new B);
auto a = std::make_shared<B>();

will capture B's deallocator and then will call B's destructor when needed 将捕获B的解除分配器,然后在需要时调用B的析构函数

std::shared_ptr<A> a((A*)(new B));

will do no such thing and will cause slicing problems in the pointed-to object. 不做这样的事情会导致指向对象的切片问题。

It is not true that nothing is changed by the fact that the pointer usage is wrapped away in a smart pointer 指针用法被智能指针包裹的事实并没有改变任何事实

For example, using unique_ptr has different behaviour: 例如,使用unique_ptr具有不同的行为:

std::unique_ptr<A> a(new B);
std::unique_ptr<A> a((A*)(new B));

will both exhibit slicing problems, while 两者都会出现切片问题

auto a = std::make_unique<B>();

won't. 惯于。

Using a plain pointer doesn't help either: 使用普通指针也无济于事:

A* a = new B{};
delete a;

is a recipe for disaster. 是一个灾难的食谱。

Example code available here . 此处提供示例代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM