Home > Software engineering >  incomplete types with shared_ptr and unique_ptr
incomplete types with shared_ptr and unique_ptr

Time:04-11

I would like to understand why unique_ptr destructors require the type to be complete upon destruction while that isn't the case with shared_ptr. This blog from Howard Hinnant briefly mentions it has to do with static vs. dynamic deleters. I'm looking for a more detailed explanation of why that might be the case (it may be compiler implementation specific in which case an example would be helpful). With dynamic deleters, does it restrict the destructor from being inlined?

CodePudding user response:

Howard Hinnant was simplifying. What he precisely meant was if you use the default deleter for std::unique_ptr, you need a complete type. For the default deleter, it simply calls delete for you.

The gist of static and dynamic deleters is

class A;

void static_delete(A* p)
{
    delete(p);
}

void (*dynamic_delete)(A*) = /* somehow */;

int main()
{
    A* p = /* somehow */;
    static_delete(p);  // undefined behaviour
    dynamic_delete(p); // maybe not
}

As long asdynamic_delete points to a function that's defined where A is also defined, you have well-defined behaviour.

To prevent undefined behaviour, the default deleter checks for a complete type, which may be implemented as

void default_delete(A* p)
{
    static_assert(sizeof(A) > 0);
    delete(p);
}

CodePudding user response:

I would like to understand why unique_ptr destructors require the type to be complete upon destruction while that isn't the case with shared_ptr

I believe that is as simple as that default destructor needs to know the size of data members. For unique_ptr the deleter is part of the object representation, whilst for shared_ptr the actual deleter is not that relevant, because it's stored in the control block, no matter what kind of deleter you use

  • Related