Shared Smart Pointer Implementation with Reference Counting

588 views Asked by At

While going through some of implementation for reference counting smart pointers, i found this type of implementation.

template<typename Type> 
class SmartRefCountPointer{
    Type* obj;
    size_t* count;  // <<--- Why pointer/ why is count on heap
}

Can you explain why this counter is moved to heap and not on stack? i would really appreciate if you can give any fail case.

4

There are 4 answers

0
Alexander Balabin On

All SmartRefCountPointers that point to the same object should also update the same counter. That's why you cannot keep the counter as a member of smart pointer class and have to use a pointer (or reference) to it that can be passed to new smart pointer on copy. It is normally allocated by the first instance of smart pointer that is contructed with an object pointer (or contructs it itself) and deleted when reference count drops to zero.

0
CashCow On

The rules of reference-counted pointers are:

  • When you copy it, the reference-count goes up
  • When you delete it, the reference-count goes down
  • If you assign it to a different one (operator=) then decrease the reference count to the one you were holding and get the counter for the one you are now assigning to, and increase it.
  • If you reset it to point to a new object, you need a new counter for it.
  • If at any time you decrease the reference count it goes down to 0, the underlying object needs to be deleted.

Now let's see how it works for copying and assigning: There are many copies about of this reference-counted pointer, and each one has the same counter with the same value. Thus not only is the "object" shared by having many pointers to it, but its counter is too. Thus it is also a pointer.

When, in your example, I do ++(*count), the pointer itself is unchanged but the value it points to has incremented by 1, not just in this shared_ptr but all the others that point to the same object.

My 3rd and 4th rules above (that it may need to point to a different counter) show also why it can't be a reference.

0
Kris On

The counter has to be shared with other instances of SmartRefCountPointer which point to the same object.

The whole point of ref-counted pointers is that there is a single place keeping track of how many references there are. This single place must thus be a global variable, or a location on the heap. The implementation you show has chosen for the later.

0
The Vivandiere On

Here is one implementation I found for reference counting smart pointers in one of the books.

template <typename T> class SmartPointer {
public:
    explicit SmartPointer(T* memory);
    SmartPointer(const SmartPointer& other);
    SmartPointer& operator =(const SmartPointer& other);
    ~SmartPointer();
    T& operator * () const;
    T* operator -> () const;
private:
    struct Intermediary {
        T* resource;
        size_t refCount;
    };
    Intermediary* data;
};

You can see that the Intermediary is allocated on the heap, not stack. The reason for it is as follows -

Imagine you have two smart pointers pointing to the same shared resource. If one of the smart pointers went out of scope, and data of type Intermediary was instead defined on the stack, then data would be cleaned up, and consequently the other smart pointer would not know the reference count or the resource any more. In order for the data object to exist even after one of the smart pointers goes out of scope, you must allocate it on the heap. This way, data remains even when one of the smart pointer sharing the resource goes out of scope.

Data is cleaned up when the reference count goes to 0 alongwith the managed resource itself.