Por que std :: shared_ptr não precisa saber o tipo completo se ele foi construído a partir de um valor não nulo?

Eu tenho uma função de fábrica em factory.h que retorna um std :: shared_ptr para uma classe base em foo.h. O factory.h usa a declaração de encaminhamento para a classe base em vez de incluir foo.h. Como o seguinte código:

factory.h:

#include <memory>

// forward declaration
class foo;

std::shared_ptr<foo> create_foo_A(int A);
std::shared_ptr<foo> create_foo_B(int A, int B);
void work_with_foo(std::shared_ptr<foo> ptr);

Em um código de cliente, se um std :: shared_ptr para foo fosse inicializado com nullptr, o compilador avisaria.

main.cpp:

#include "factory.h"
int main()
{
    int type = 1;

    std::shared_ptr<foo> ptr(nullptr);    // <--- compile warning
    if (type == 1)
        ptr = create_foo_A(5566);
    else
        ptr = create_foo_B(5566, 7788);
    work_with_foo(ptr);

    return 0;
}

A mensagem de aviso é:

warning C4150 : deletion of pointer to incomplete type 'foo'; no destructor called

É razoável, já que o std :: shared_ptr não conhece o tipo completo de foo. Este aviso pode ser removido se main.cpp incluísse foo.h.

Mas se std :: shared_ptr foi inicializado com non-nullptr, a compilação não avisaria. main.cpp:

#include "factory.h"
int main()
{
    int type = 1;

    if (type == 1)
    {
        std::shared_ptr<foo> ptr = create_foo_A(5566);    // <--- OK
        work_with_foo(ptr);
    }
    else
    {
        std::shared_ptr<foo> ptr = create_foo_B(5566, 7788);    // <--- OK
        work_with_foo(ptr);
    }

    return 0;
}

Nesta cena, por que o std :: shared_ptr não precisa conhecer o tipo completo de classe foo? É muito diferente quando std :: shared_ptr é construído com nullptr e não nulo?

questionAnswers(3)

yourAnswerToTheQuestion