Why doesn't std :: shared_ptr need to know the full type if it is constructed from a non-empty one?

I have a factory function in factory.h that returns std :: shared_ptr to the base class in foo.h. factory.h uses a forward declaration for the base class instead of including foo.h. As the following code:

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);

In client code, if std :: shared_ptr for foo was initialized with nullptr, the compiler warned.

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;
}

Warning message:

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

This is reasonable since std :: shared_ptr does not know the full type foo. This warning can be removed if main.cpp is enabled foo.h.

But if std :: shared_ptr was initialized using non-nullptr, the compiler will not warn. 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;
}

std:: shared_ptr foo? , std:: shared_ptr nullptr non-null?

+2
3

:

std::shared_ptr<foo> ptr(nullptr);

. foo. , , nullptr . :

std::shared_ptr<foo> ptr;

:

constexpr shared_ptr(nullptr_t) : shared_ptr() { }

std:: shared_ptr foo?

create_foo_A create_foo_B foo. .

shared_ptr<T>::shared_ptr(U*) U. . :

fooobar.com/questions/9943/...

, :

std::shared_ptr<foo> ptr((foo*)0);

undefined. , V++ . lib++ . nullptr , , ++ 11.

, foo.


[util.smartptr.shared.dest]

~shared_ptr();

:

  • *this shared_ptr (use_count() > 1), .

[util.smartptr.shared.const]

constexpr shared_ptr() noexcept;

: shared_ptr.


[util.smartptr.shared]

:

constexpr shared_ptr(nullptr_t) : shared_ptr() { }
+3

, std::shared_ptr - , .

-, , , , , C.

- . std::atomic<unsigned>, std::shared_ptr /, / .

- - , .

std::shared_ptr , / / std::shared_ptr. , !

std::shared_ptr<Foo> , . - , Foo: Foo!

std::shared_ptr , nullptr, .

, : , std::shared_ptr<Foo> std::shared_ptr, , Foo::~Foo (.. of Foo).

, , std::shared_ptr, : , std::shared_ptr , , .

, nullptr, , .

std::shared_ptr<foo> ptr(nullptr); Foo, std::shared_ptr<foo> ptr(nullptr, [](foo*){});, do-nothing.

+3

, .: -)

, create_foo_A() create_foo_B(), , , , , foo. , foo; , , , .

:

std::shared_ptr<foo> ptr(nullptr);

foo, . foo, , , ( ) .

+1

All Articles