下面是对shared_ptr 和 unique_ptr这两种类的简单实现。
shared_ptr
template<typename T>
struct DefaultDeleter {
void operator()(T *ptr) {
if (nullptr != ptr) {
delete ptr;
ptr = nullptr;
}
}
};
template <typename T>
class SharedPtr {
public:
SharedPtr() : pointer_{nullptr}, reference_count_{nullptr} {}
SharedPtr(T* pointer, std::function<void(T*)> deleter=DefaultDeleter<T>())
: pointer_{pointer}, reference_count_{nullptr} {
add_reference_count();
deleter_ = deleter;
}
SharedPtr(const SharedPtr<T>& copy) {
if (this != ©) {
this->pointer_ = copy.pointer_;
this->reference_count_ = copy.reference_count_;
add_reference_count();
}
}
SharedPtr& operator=(const SharedPtr<T>& other) {
if (this != &other) {
remove_reference_count();
this->pointer_ = other.pointer_;
this->reference_count_ = other.reference_count_;
this->deleter_ = other.deleter_;
add_reference_count();
}
return *this;
}
bool operator==(const SharedPtr<T>& other) {
return this->pointer_==other.pointer_;
}
bool operator!=(const SharedPtr<T>& other) {
return !operator==(other);
}
T* operator*() {
assert(nullptr == pointer_);
return (*pointer_);
}
T operator->() const {
return pointer_;
}
int use_count() {
if (nullptr != reference_count_) {
return *reference_count_;
} else {
return 0;
}
}
void reset(T *ptr) {
remove_reference_count();
pointer_ = ptr;
}
T* get() {
return pointer_;
}
~SharedPtr() {
remove_reference_count();
}
private:
void add_reference_count() {
if (nullptr != reference_count_) {
(*reference_count_)++;
} else {
reference_count_ = new size_t(1U);
}
}
void remove_reference_count() {
if (nullptr !=reference_count_) {
(*reference_count_)--;
if ((*reference_count_) == 0) {
deleter_(pointer_);
delete reference_count_;
pointer_ = nullptr;
reference_count_ = nullptr;
}
}
}
T* pointer_;
size_t* reference_count_;
std::function<void(T*)> deleter_;
};
这里reference_count_和pointer_一样都是指针类型,是为达到共享的目的,在各个SharedPtr都需要知道引用计数的值,并且都可以修改。在传入删除器时,默认是delete的方式,有传入自定义的删除器时使用自定义的删除器。
引用计数这一点和之前看到过的string类的copy-on-write实现挺类似的,感兴趣的同学可以看一下这篇文章:https://blog.csdn.net/haoel/article/details/24058。
unique_ptr
template <typename T, typename Deleter = DefaultDeleter<T>>
class UniquePtr {
public:
UniquePtr(T* ptr = nullptr) : pointer_{ptr} {};
UniquePtr(const UniquePtr& ptr)=delete;
UniquePtr& operator=(const UniquePtr& ptr)=delete;
~UniquePtr() {
if (nullptr != pointer_) {
deleter_(pointer_);
pointer_ = nullptr;
}
}
T* release() {
T* ret_ptr = pointer_;
pointer_ = nullptr;
return ret_ptr;
}
T* get() {
return pointer_;
}
T& operator*() {
return *pointer_;
}
T* operator->() {
return pointer_;
}
void reset(T* ptr) {
if (nullptr != pointer_) {
deleter_(pointer_);
}
pointer_ = ptr;
}
operator bool() const {
return nullptr != pointer_;
}
private:
T* pointer_;
Deleter deleter_;
};
可以看到,UniquePtr的拷贝的构造和赋值构造都delete了,实现了独享。默认的删除器还是detele。
对于std::shared_ptr和std::unique_ptr来讲,指定删除器还是有区别的。unique_ptr制定删除器时必须明确删除器的类型,在编译时绑定。而对于shared_ptr来说,删除器类型是在运行时绑定。