Why doesn't std::shared_ptr need to know complete type if it's constructed from non-null?

后端 未结 3 429
失恋的感觉
失恋的感觉 2021-01-22 04:47

I have a factory function in factory.h which returns an std::shared_ptr to a base class in foo.h. factory.h uses

3条回答
  •  一生所求
    2021-01-22 05:22

    So std::shared_ptr is three things wrapped up in one small neat package.

    First, it is a pointer to some data, with overrides to give you access to it that make using it much like using a raw C pointer.

    The second part is a reference counter. It keeps track of the equivalent of an std::atomic that all std::shared_ptr copies off the first increment/decrement as they come into / go out of scope.

    The third part is a destruction function -- or a pointer to said destruction function, to be more exact.

    When you copy a std::shared_ptr from another, it uses the reference counter/destruction function/pointer to data of the source std::shared_ptr. So it does not need to write a destruction function, nor does it need to know what the destruction function does!

    When you create a std::shared_ptr without copying it, it must create the destruction function. The default destruction function is one that calls the destructor of Foo: which requires the full declaration of Foo!

    std::shared_ptr will call the destruction function even if the pointer is nullptr, so even in the empty case it need write that destruction function.

    So the short story is: anywhere you create a std::shared_ptr not by copying or moving from another std::shared_ptr, you must either supply a manual destruction function, or you must have Foo::~Foo visible (ie, the full declaration of Foo).

    The cases where you called a function that returned a std::shared_ptr copied them from inside the body of the function: within that body, wherever those std::shared_ptr eventually came from, one of the two requirements above where met.

    The case where you simply create it on nullptr it must write and store the destruction function, and that requires full access to the class.

    If you really need to std::shared_ptr ptr(nullptr); without access to foo, try std::shared_ptr ptr(nullptr, [](foo*){});, which should pass in a do-nothing destruction function.

提交回复
热议问题