前言
智能指针本质上并不神秘,其实就是 RAII 资源管理功能的自然展现而已。本文将介绍如何实现 C++中智能指针的 shared_ptr。
原理简介
多个不同的 shared_ptr
不仅可以共享一个对象,在共享同一对象时也需要同时共享同一个计数。当最后一个指向对象(和共享计数)的 shared_ptr
析构时,它需要删除对象和共享计数。
实现过程
我们先实现共享计数的接口,这个 shared_count
类除构造函数之外有三个方法:一个增加计数,一个减少计数,一个获取计数。
class shared_count {
public:
shared_count() : count_(1) {
}
void add_count()
{
++count_;
}
long reduce_count()
{
return --count_;
}
long get_count() const
{
return count_;
}
private:
long count_;
};
接下来可以实现我们的引用计数智能指针了。首先是构造函数、析构函数和私有成员变量:
template <typename T>
class shared_ptr {
public:
explicit shared_ptr(T* ptr = nullptr)
: ptr_(ptr)
{
if (ptr) {
shared_count_ = new shared_count();
}
}
~shared_ptr()
{
if (ptr_ && !shared_count_->reduce_count()) {
delete ptr_;
delete shared_count_;
}
}
private:
T* ptr_;
shared_count* shared_count_;
};
构造函数会构造一个 shared_count
出来。析构函数在看到 ptr_
非空时(此时根据代码逻辑, shared_count
也必然非空),需要对引用数减一,并在引用数降到零时彻底删除对象和共享计数。
为了方便实现赋值(及其他一些惯用法),我们需要一个新的 swap
成员函数:
void swap(shared_ptr& rhs)
{
using std::swap;
swap(ptr_, rhs.ptr_);
swap(shared_count_, rhs.shared_count_);
}
赋值函数,拷贝构造和移动构造函数的实现:
shared_ptr(const shared_ptr& other)
{
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}
template <typename U>
shared_ptr(const shared_ptr<U>& other) noexcept
{
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ =</