Why is the reference count not 2?

95 Views Asked by At
#include <iostream>
#include <memory>

class type
{
public:
    type()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    ~type()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

};

int main()
{
    type* p = new type();

    std::shared_ptr<type> ptr1(p);

    std::shared_ptr<type> ptr2(p);

    int count = ptr2.use_count();
}


Two shared_ptrs are referencing the same raw pointer, so why is the ref count 1?

image

It refers to the same address.

1

There are 1 best solutions below

0
463035818_is_not_an_ai On BEST ANSWER

Here

type* p = new type();

p is a raw owning pointer. Raw owning pointers should be avoided all together. Raw owning pointers have no support for managing ownership, it is all up to you.

Next,

std::shared_ptr<type> ptr1(p);

you transfer ownership from p to ptr1. The shared pointer does support managing ownership. Internally it keeps a reference count when you share ownership via this instance.

Next,

std::shared_ptr<type> ptr2(p);

you transfer ownership from p to ptr2. However, you did already transfer ownership away from p. There is already a second seperate shared pointer that does own the object. ptr2 cannot know about that already existing other shared pointer, because you transfer ownership from p. p is a raw pointer and has no support to manage ownership.

The reference count of both shared pointers is 1, because they both believe they would be the only owner of the object.


If you want to get a second shared pointer that shares ownership with an already existing shared pointer, you can make a copy:

type* p = new type();
std::shared_ptr<type> ptr1(p);
std::shared_ptr<type> ptr2(ptr1);
std::cout << ptr2.use_count();

In that code, ptr1 and ptr2 share the ownership of the object. Whichever pointer leaves the scope last will destroy the object. In your code both will attempt to destroy the object, because you made them both the sole owner of the object.

Smart pointers do not release you from having a clear concept of ownership, but rather they enable you to express it clearly in the code. You can still use them wrong, its just a little harder as compared to using raw pointers.