#include
#include
class SharedCount {
public:
SharedCount() : count_{1} {}
void add() { ++count_; }
void minus() { --count_; }
int get() const { return count_; }
private:
std::atomic count_;
};
template
class SharedPtr {
public:
template
friend class SharedPtr;
template
friend SharedPtr static_pointer_cast(const SharedPtr& p);
SharedPtr(T* ptr) : ptr_{ptr}, ref_count_{new SharedCount} {}
SharedPtr() : ptr_{nullptr}, ref_count_{new SharedCount} {}
~SharedPtr() { clean(); }
SharedPtr(const SharedPtr& p) {
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}
SharedPtr(SharedPtr&& p) {
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
}
SharedPtr& operator=(const SharedPtr& p) {
if (this == &p) return *this;
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
return *this;
}
SharedPtr& operator=(SharedPtr&& p) {
if (this == &p) return *this;
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
return *this;
}
int use_count() { return ref_count_->get(); }
T* get() const { return ptr_; }
T* operator->() const { return ptr_; }
T& operator*() const { return *ptr_; }
operator bool() const { return ptr_; }
private:
template
SharedPtr(const SharedPtr& p, T* ptr) {
this->ptr_ = ptr;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}
void clean() {
if (ref_count_) {
ref_count_->minus();
if (ref_count_->get() == 0) {
if (ptr_) delete ptr_;
delete ref_count_;
}
}
}
T* ptr_;
SharedCount* ref_count_;
};
template
SharedPtr static_pointer_cast(const SharedPtr& p) {
T* ptr = static_cast(p.get());
return SharedPtr(p, ptr);
}
struct A {
A() { std::cout << "A() \n"; }
~A() { std::cout << "~A() \n"; }
};
struct B : A {
B() { std::cout << "B() \n"; }
~B() { std::cout << "~B() \n"; }
};
void test_cast_shared() {
B* a = new B;
SharedPtr ptr(a);
{
std::cout << ptr.use_count() << std::endl;
SharedPtr b = static_pointer_cast(ptr);
std::cout << ptr.use_count() << std::endl;
SharedPtr c = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr d = ptr;
std::cout << ptr.use_count() << std::endl;
}
std::cout << ptr.use_count() << std::endl;
}
void test_simple_shared() {
A* a = new A;
SharedPtr ptr(a);
{
std::cout << ptr.use_count() << std::endl;
SharedPtr b = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr c = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr d = std::move(b);
std::cout << ptr.use_count() << std::endl;
}
std::cout << ptr.use_count() << std::endl;
}
int main() { test_simple_shared(); }