重学C++系列之智能指针简单介绍

一、什么是智能指针

        在使用堆内存时,就像使用栈内存空间一样,可以实现自释放的功能,智能指针在C++库中也是类模板之一。

二、智能指针有几种

        有四种。auto_ptr, unique_ptr, shared_ptr, weak_ptr 其中后三个是C++11支持,第一个已经被C++弃用且被unique_ptr 代替,不推荐使用。

        1、unique_ptr, 实现了独占式拥有的概念,同一个时间只能有一个智能指针可以指向该对象,因为无法进行拷贝构造和拷贝赋值,但是可以进行移动构造和移动赋值。

        2、share_ptr, 实现了共享式拥有的概念,即多个智能指针可以指向相同的对象,该对象及相关资源会在其所指对象不再使用之后,自己释放与对象相关的资源。

        3、weak_ptr, 解决share_ptr相互引用时,两个指针的引用计数永远不会下降为0,从而导致死锁问题。而weak_ptr 是对对象的一种弱引用,可以绑定share_ptr, 但不会增加对象的引用计数。

        4、atuo_ptr, 实现独占式拥有的概念,同一时间只能有一个智能指针可以指向该对象;但atuo_ptr在C++17中被摒弃,其主要问题在于:对象所有权的转移,比如在函数传参过程中,对象所有权不会返还,从而存在潜在的内存崩溃问题;不能指向数组,也不能作为STL容器的成员。

三、智能指针的特点

        1、在C++库中也是类模板之一。

        2、实际上将指针封装在一个类,通过对象来管理指针。

        3、作用主要用来管理内存,在C++中,是一种管理资源,避免泄漏内存的习惯用法,也称RAII(资源获取及初始化)

四、案例

        1、auto_ptr的简单实现

#include 

using namespace std;


class Test1
{
private:
    int a;
public:
    Test1(int a = 0)
    {
        cout << "Test1()" << endl;
        this->a = a;
    }
    ~Test1()
    {
        cout << "~Test1()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};

class Test2
{
private:
    int a;
public:
    Test2(int a = 0)
    {
        cout << "Test2()" << endl;
        this->a = a;
    }
    ~Test2()
    {
        cout << "~Test2()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};

template 
class myauto_ptr
{
private:
    T *ptr;
public:
    // 使用类模板的方式来适应多个类
    myauto_ptr(T *ptr = T ())
    {
        this->ptr = ptr;
    }

    ~myauto_ptr()
    {
        delete ptr;     // 重点在这里
        cout << "~myauto_ptr" << endl;
    }

    // 重载成员函数, 让本类的指针成员变量可以调用T类对象的成员函数
    T* operator ->()
    {
        return ptr;
    }

    T& operator *()
    {
        return *ptr;
    }
};




int main()
{
    Test1 *p1 = new Test1(10);
    // delete p1;   // 如果没有这步,会造成内存泄漏
    Test2 *p2 = new Test2(20);

    myauto_ptr p3(new Test1(100));
    myauto_ptr p4(new Test2(200));

    p3->show();
    (*p4).show();
    

    return 0;
}

重学C++系列之智能指针简单介绍_第1张图片

        2、share_ptr的简单实现

#include 

using namespace std;

// 定义一个共享的全局变量,用来描述指向某个对象的指针个数
int share_count = 1;    

class Test1
{
private:
    int a;
public:
    Test1(int a = 0)
    {
        cout << "Test1()" << endl;
        this->a = a;
    }
    ~Test1()
    {
        cout << "~Test1()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};



template 
class myshare_ptr
{
private:
    T *ptr;
public:
    // 使用类模板的方式来适应多个类
    myshare_ptr(T *ptr = T ())
    {
        this->ptr = ptr;
    }

    ~myshare_ptr()
    {
        cout << "count :" << share_count-1 << endl;
        if(this->ptr != nullptr && --share_count == 0)
        {
            delete ptr;     // 重点在这里
        }
        
        cout << "~myshare_ptr" << endl;
    }
    myshare_ptr(const myshare_ptr& other)
    {
        this->ptr = other.ptr;
        share_count++;
    }
    T& operator = (const myshare_ptr& other)
    {
        share_count++;
        this->ptr = other.ptr;
        return *this->ptr;
    }
    

    // 重载成员函数, 让本类的指针成员变量可以调用T类对象的成员函数
    T* operator ->()
    {
        return ptr;
    }

    T& operator *()
    {
        return *ptr;
    }
};




int main()
{
    Test1 *p1 = new Test1(10);
    // delete p1;   // 如果没有这步,会造成内存泄漏
    
    myshare_ptr p2(new Test1(100));

    myshare_ptr p3 = p2;
    myshare_ptr p4 = p2;

    p3->show();
    

    return 0;
}

重学C++系列之智能指针简单介绍_第2张图片

五、总结

        本篇只是简单讲解一下四种智能指针,并简单实现了两个简单的案例,实际使用中还是用C++提供的智能指针。了解内部原理有助于正确使用。

你可能感兴趣的:(C++语言设计,c++)