一、原因

动态内存的管理需要程序员手动申请和释放,动态内存的分配和释放用new和delete运算符来完成,如果new和delete的操作次数不一致,则会造成内存泄漏、二次释放等问题,为了更加方便和安全地使用动态内存,c++11引入了智能指针的概念

二、概念

智能指针是指能够自动释放所指向的对象的指针,它本质上不是一个指针,而是封装了一个普通指针的类对象,其设计思想来源于“RAII”,即“资源获取就是初始化”,通过一个对象,在其构造时获取资源,在其生命周期结束自动调用析构函数释放所指向的对象,使用智能指针需要include<memory>头文件</memory>

三、分类

1.auto_ptr

同一时刻只有一个指针指向实际对象,不支持拷贝和赋值操作

2.unique_ptr

同一时刻只有一个unique_prt指向一个给定对象,也不支持拷贝和赋值操作,可以使用move转移所有权

unique_ptr<int> p3 = std::move(p1); //现在那块内存归p3所有, p1成为无效的指针

3.shared_ptr

多个指针可以指向同一个对象,每个shared_ptr都有一个关联的计数器,用来表示所指向的对象被引用的次数,支持赋值和拷贝,当计数器为0时对象会被释放(可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,因为一个是类,一个是指针)

4.weaked_ptr

一种不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。

int main() {
    {
        std::shared_ptr<int> sh_ptr = std::make_shared<int>(10);
        std::cout << sh_ptr.use_count() << std::endl;
        std::cout << *sh_ptr<< std::endl; //获得指针的值
        std::weak_ptr<int> wp(sh_ptr);//弱指针可以观测资源的使用情况
        std::cout << wp.use_count() << std::endl;
        if(!wp.expired()){                      //lock()函数,从被观测的shared_ptr获得一个可用的
            std::shared_ptr<int> sh_ptr2 = wp.lock(); //shared_ptr对象, 从而操作资源
            *sh_ptr = 100;
            std::cout << wp.use_count() << std::endl;
        }
    }
    //delete memory
}

四、实现shared_ptr

template<typename T>
class sharedptr {
public:
    //构造函数
    sharedptr(T *ptr):_ptr(ptr),_cnt(new int(1)) {
        cout << "构造" << endl;
    }
    //拷贝构造
    sharedptr(sharedptr<T> sp):_ptr(sp._ptr),_cnt(sp._cnt){
        cout << "拷贝构造" << endl;
        ++(*_cnt);
    }
    //赋值操作运算符
    sharedptr<T> operator=(sharedptr<T> sp) {
        cout << "赋值操作运算符" << endl;
        if (_ptr != sp._ptr) {
            if (--(*_cnt) == 0) {//计数器为0,则释放指针指向的对象
                delete _ptr;
                delete _cnt;

            }
            _ptr = sp._ptr;
            _cnt = sp._cnt;
            ++(*_cnt);

        }
        return *this;
    }
    T * operator->() {
        return _ptr;
    }
    T& operator*() {
        return *_ptr;
    }
    int getcnt() {
        return *_cnt;
    }
    ~sharedptr(){
        cout << "析构" << endl;
        if (--(*cnt) == 0) {
            delete _ptr;
            _ptr = nullptr;
            delete _cnt;
            _cnt = nullptr;
        }
    }
private:
    int *_cnt;
    T *_ptr;
};