This is an implementation to simulate the basic functionality of c++ shared_ptr. This doesn't provide features like custom deleter and make_shared().
I would really appreciate any feedback to improve the below code, any other api's that I should be providing etc.
#ifndef SHARED_PTR_H_
#define SHARED_PTR_H_
#include <utility>
namespace kapil {
template <typename T>
class shared_ptr {
private:
T* ptr_; // data pointer
int* ref_count_; // reference count pointer
void decrement_ref_count_and_delete_if_needed() {
if (ref_count_) {
--(*ref_count_);
if (*ref_count_ == 0) {
delete ptr_;
delete ref_count_;
ptr_ = nullptr;
ref_count_ = nullptr;
}
}
}
public:
constexpr shared_ptr() noexcept : ptr_{nullptr}, ref_count_{nullptr} {}
constexpr explicit shared_ptr(T* ptr) { // constructor
ptr_ = ptr;
ref_count_ = new int{1};
}
shared_ptr(const shared_ptr& other) noexcept { // copy constructor
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_ != nullptr) {
++(*ref_count_);
}
}
shared_ptr(shared_ptr&& other) noexcept { // move constructor
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
other.ptr_ = nullptr;
other.ref_count_ = nullptr;
}
~shared_ptr() noexcept { // destructor
decrement_ref_count_and_delete_if_needed();
}
shared_ptr& operator = (const shared_ptr& other) noexcept { // assignent operator
if (this != &other) {
decrement_ref_count_and_delete_if_needed();
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
return *this;
}
shared_ptr& operator = (shared_ptr&& other) noexcept { // move assignment operator
*this = other;
}
T* get() const noexcept {
return ptr_;
}
void reset() noexcept {
decrement_ref_count_and_delete_if_needed();
}
void reset(T* ptr) {
decrement_ref_count_and_delete_if_needed();
ptr_ = ptr;
if (!ref_count_) {
ref_count_ = new int{1};
}
*ref_count_ = 1;
}
int use_count() const noexcept {
return *ref_count_;
}
void swap (shared_ptr& other) {
std::swap(ptr_, other.ptr_);
std::swap(ref_count_, other.ref_count_);
}
T& operator * () const {
return *ptr_;
}
T* operator -> () const noexcept {
return ptr_;
}
explicit operator bool() const noexcept {
return (ptr_ != nullptr);
}
friend bool operator == (const shared_ptr& lhs, const shared_ptr& rhs) noexcept {
return (lhs.ptr_ == rhs.ptr_);
}
friend bool operator != (const shared_ptr& lhs, const shared_ptr& rhs) noexcept {
return !(lhs == rhs);
}
}; // class shared_ptr
template <typename T>
void swap(shared_ptr<T>& lhs, shared_ptr<T>& rhs) { // swap function in namespace to facilitate ADL
lhs.swap(rhs);
}
} // namespace kapil
#endif