shared_ptr and slicing

送分小仙女□ 提交于 2019-12-01 00:17:01

问题


Someone I worked with once said that shared_ptr was unsafe and would slice when casting from a derived class to a base class (i.e. upcasting). For example if there were 2 classes A and B where B derived from A, then

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

shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T* can be implicitly converted to U*.

implied that it's safe to use in those contexts but he didn't seem to think so.


回答1:


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.

Simplified it could look e.g. 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.




回答2:


It is true that object slicing doesn't apply to pointers

Pointers are PODs (just for the record: shared_ptrs aren't).

The question quotes:

shared_ptr can be implicitly converted to shared_ptr whenever T* can be implicitly converted to U*.

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. This is the reason why the shared_ptr object itself doesn't slice.

It is not true that object slicing cannot be a concern

Consider a class hierarchy A, B with no virtual destructors.

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

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:

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.



来源:https://stackoverflow.com/questions/3305753/shared-ptr-and-slicing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!