Reputation: 1180
I have seen several implementations of shared_ptr, for example here. All of them declare ref_count
as int*
. I don't understand what would we lose if it is simply an int
. Thanks!
template <class T>
class shared_ptr {
T* ptr;
int* ref_count;
/**
* Initializes the ref count used for tracking the usage.
*/
void initialize_ref_count() {
if (ref_count != nullptr)
return;
try {
ref_count = new int;
*ref_count = 1;
}
catch (std::bad_alloc& e) {
std::cerr << "Memory allocation error: " << e.what();
}
}
}
Upvotes: 8
Views: 1892
Reputation: 21576
First, in other to share something, you need to put it somewhere where others can have access to. As noted by @Igor Tandetnik. So an object of dynamic storage duration would do the job well. An object of a static storage duration with dynamic initialization could do it too, but the object will exist for the remainder of the program, which we do not want.
Secondly, shared_ptr
is a bit more complicated than that. A typical shared_ptr
would refer to a Control Block. This Control block usually contains:
For thread safety, the shared reference count and weak reference count is typically held by an atomic type.
EDIT: See @Passer By's comment.
Upvotes: 3
Reputation: 8531
As you can see in the implementation you provided (in your link), when a shared pointer is copy constructed or copy assigned, the pointer to the reference counter (ref_count
) is shared between all the instances that manage the same pointer:
// Copy constructor
shared_ptr(const shared_ptr& copy) {
ptr = copy.ptr;
ref_count = copy.ref_count; // see here
if (ref_count != nullptr) {
++(*ref_count);
}
}
// Assignment operator
shared_ptr& operator=(const shared_ptr& copy) {
ptr = copy.ptr;
ref_count = copy.ref_count; // see here
if (ref_count != nullptr) {
++(*ref_count);
}
return *this;
}
In that way, all the instances of that shared pointer, refer to the same memory location to track the ref counter, and the last shared_ptr
will be able to know if it needs to do the cleaning (delete
the allocated memory):
~shared_ptr() {
--(*ref_count);
if (*ref_count == 0) {
delete ref_count;
ref_count = nullptr;
delete ptr;
ptr = nullptr;
}
}
This answer was based in the example provided by the OP for simplicity. A shared_ptr
implementation is far more complicated that the one in the example (think about atomicity, race conditions, etc...).
Upvotes: 8