C++的四种智能指针及简单实现

参考:C++智能指针讲解及模拟实现

一、auto_ptr

  • auto_ptr有拷贝语义,拷贝后源对象变为空指针,可能引发严重问题
template<class T>
class my_unique_ptr{
private:
    T *_ptr;
public:
    // 普通构造函数
    my_unique_ptr(T *ptr) : _ptr(ptr){}
    // 拷贝构造函数
    my_unique_ptr(my_unique_ptr<T> a_ptr){
        _ptr = a_ptr._ptr;
        a_ptr._ptr = nullptr;
    }

    // 析构函数
    ~my_unique_ptr(){
        if(_ptr){
            delete _ptr;
            _ptr = nullptr;
        }
    }

    // 重载*运算符
    T& operator*(){
        return *_ptr;
    }

    // 重载->运算符
    T* operator->(){
        return _ptr;
    }

    // 重载=运算符
    my_unique_ptr<T>& operator=(my_unique_ptr<T> a_ptr){
        if(this != &a_ptr){
            delete _ptr;
            _ptr = a_ptr._ptr;
            a_ptr.ptr = nullptr;
        }
        return *this;
    }
};

二、unique_ptr

  • 与auto_ptr类似,但是没有拷贝语义,但是允许使用移动语义
template<class T>
class my_unique_ptr{
private:
    T *_ptr;
public:
    // 普通构造函数
    my_unique_ptr(T *ptr) : _ptr(ptr){}
    // 拷贝构造函数
    my_unique_ptr(my_unique_ptr<T> a_ptr)=delete;

    // 析构函数
    ~my_unique_ptr(){
        if(_ptr){
            delete _ptr;
            _ptr = nullptr;
        }
    }

    // 重载*运算符
    T& operator*(){
        return *_ptr;
    }

    // 重载->运算符
    T* operator->(){
        return _ptr;
    }

    // 重载=运算符
    my_unique_ptr<T>& operator=(my_unique_ptr<T> a_ptr)=delete;
public:
    const T* get(){
        return _ptr;
    }

    size_t use_count(){
        return *_count;
    }
};

三、shared_ptr

  • 多个shared_ptr可以指向同一处资源,当所有shared_ptr被只放时,该处资源才被释放
template<class T>
class my_shared_ptr{
private:
    T *_ptr;
    int *_count;

public:
    // 普通构造函数
    my_shared_ptr(T *ptr) : _ptr(ptr), _count(new int(1)){}
    // 拷贝构造函数
    my_shared_ptr(my_shared_ptr<T> &s_ptr){
        _ptr = s_ptr._ptr;
        _count = s_ptr._count;
        ++(*_count);
    }
    // 析构函数
    ~my_shared_ptr(){
        --(*_count);
        if(0 == (*_count)){
            if(_ptr){
                delete _ptr;
            }
            delete _count;
        }
    }

    // 重载*运算符
    T& operator*(){
        return *_ptr;
    }

    // 重载->运算符
    T* operator->(){
        return ptr;
    }

    // 重载=运算符
    my_shared_ptr<T>& operator=(my_shared_ptr<T> u_ptr){
        // 避免自己给自己赋值
        if(_ptr != u_ptr._ptr){
            // 减少原先指向对象的引用
            --(*_count);
            if(0 == (*_count)){
                if(_ptr){
                    delete _ptr;
                }
                delete _count;
            }
            // 拷贝
            _ptr = u_ptr._ptr;
            _count = u_ptr._count;
            ++(*count);
        }
    }
};

四、weak_ptr

  • weak_ptr是一种弱引用型指针,不控制所指向对象生存期的智能指针,主要为了解决循环引用问题和悬空指针问题
template<class T>
class my_weak_ptr
{
private:
    T *_ptr;
    size_t _shared_count;
public:
    my_weak_ptr(const my_shared_ptr<T> &s_ptr) _ptr(s_ptr._ptr), _shared_count(s_ptr._count);
    my_weak_ptr(const my_weak_ptr<T> &w_ptr) _ptr(w_ptr._ptr), _shared_count(s_ptr._shared_count);

    // 重载*运算符
	T& operator*()
	{
		return *_ptr;
	}

    // 重载->运算符
	T* operator->()
	{
		return _ptr;
	}

    // 重载=运算符
    my_weak_ptr<T>& operator=(const my_shared_ptr<T>& s_ptr)
	{
		_ptr = s_ptr.get();
		return *this;
	}
};