• c++ 踩坑大法好 智能指针


    1,智能指针是啥?

    普通指针基本上就是一个变量,它的的生命周期和变量的作用域有关,局部变量在走出作用域以后就会销毁,全局变量可能程序运行完了就销毁了。

    new出来的指针和普通指针的区别在于,new出来的那块内存区域是不会自动被释放的,需要你手动调用delete才能释放,然而由于种种原因,new----delete这俩节奏总是出状况,于是有人想到了自动回收的指针

    智能指针根本上是一个class,你可以生成一个class实例用以管理一块内存,内存中放上你想放的东西,一方面该实例记录着该内存的地址,类型等信息,你可以和普通指针似的使用它,另一方面它记录对该内存的引用,当引用为0,就把该指针指向的内存区域释放出来。

    2,shared_ptr共享指针:

    1),基本语法

    #include <stdarg.h>
    #include <iostream>
    #include <string>
    #include <memory>    //shared_ptr
    using namespace std;
    
    int main(void)
    {
        /*使用传入参数的方法生成智能指针*/
        shared_ptr<int> p1(new int);
        //创建一个int型的智能指针对象:在堆上创建两块内存,一个用于存储int,另一个用于记录对刚刚那块内存的引用的数量,初始化引用数量为1.
        //语法含义:shared_ptr是个模板类,使这个模板类按照int类型生成class类,然后创建p1对象,并且传递参数:new int,new int的意思是申请一个int大小的内存块,并且返回该内存块的地址。
        cout << p1.use_count() << endl;
        //检查p1所指向的内存块的引用计数,当前为1
    
        shared_ptr<int> p2 = p1;
        //创建新的智能指针p2也指p1指向的内存,这样的写法也可以:shared_ptr<int> p(p1)
        cout << p1.use_count() << endl;
        //现在引用数目为2
    
        p2.reset();
        //取消p2的指向,带参数的话p2会建立指向新内存
        cout << p1.use_count() << endl;
        //现在引用数目为1
    
        p2 = nullptr;
        //把p2重置为nullptr(这大约是空指针约定俗成的写法,暂不讨论)
        if (p2 == nullptr) {
            printf("empty ptr
    ");
        }
    
        /*使用构造函数来创建智能指针,推荐使用这种方法*/
        shared_ptr<int> p3 = std::make_shared<int>();
        //语法含义:int型智能指针shared_ptr的类实例p1的地址是什么呢?是模板函数make_shared根据int类型生成的存值内存的地址,当然它还同时生成了存储引用的内存
    
    
        //有人说使用智能指针存储数组会有问题,因为数组释放内存需要用delete [] ptr;而不是delete ptr;需要重写析构方法
        //不清楚内部机制以及看不懂源码的我,最后决定不用智能指针存储数组,问题暂时放着吧
        /*以下是错误示范,虽然也能跑*/
        shared_ptr<int[10]> p4 = std::make_shared<int[10]>();
        cout <<"array1:"<< p4.use_count() << endl;
        p4.reset();
        cout <<"array2:"<< p4.use_count() << endl;
    
        return 0;
    }

     2),如何从智能指针中获取数据?

    #include <stdarg.h>
    #include <iostream>
    #include <string>
    #include <memory>    //shared_ptr
    #include <vector>
    using namespace std;
    
    int main(void)
    {
        /*普通的vector的使用:*/
    
        vector<int> hehe = { 4,5 };
        vector<int> hehe1 = vector<int>(2,4);
        //生成一个内容是两个4的int的普通vector
        hehe1.push_back(4);
        //普通vector追加数据
        for (auto itt : hehe1)
        {
            printf("orign:%d
    ", itt);
        }
    
        /*智能指针指向的vector怎么用?*/
    
        shared_ptr < vector<int > > vi0(new vector<int>);
        //声明一个智能指针指向int的vector
        vi0->push_back(1);
        vi0->push_back(2);
        //智能指针vector追加数据,1和2,注意操作符是这样的:->
        for (auto itt : (*vi0))
        {
            printf("shared_ptr:%d
    ", itt);
        }
    
        //shared_ptr < vector<int > > vi = make_shared<vector<int >>(hehe);
        shared_ptr < vector<int > > vi = make_shared<vector<int >>(2,3);
        //使用构造函数声明并且初始化一个智能指针指向int的vector,内容是两个3
        int len1 = (*vi).size();
        int len2 = vi->size();
        //两种方法获取vector长度,一个是使用*翻译智能指针,另一个是使用:->
        printf("len1:%d,len2:%d
    ",len1, len2);
        
        printf("use count1:%d
    ", vi.use_count());
        //智能指针本来只有一个引用
        vector<int> *test = vi.get();
        //据说是让智能指针返会一个普通指针,
        printf("use count2:%d
    ", vi.use_count());
        //看来get()方式并不能让智能指针引用增加,现在它还是只有一个引用
    
        printf("address of test:%p
    ", test);
        //vi销毁以前查看一下test地址
        vi = nullptr;
        //智能指针销毁
        printf("use count3:%d
    ", vi.use_count());
        //现在引用为0,确实销毁了
        printf("address of test:%p
    ", test);
        //销毁以后地址还是指向那块内存,test的地址没有改变
        printf("len of test : %d
    ", (*test).size());
        //但是已经不能获取到长度,应该是已经没法使用或者地址上全都填充0了,返回0
    
        *test= vector<int>(2, 4);
        //但是依旧可以在那块内存上进行操作,比如重新赋值
        printf("len of test : %d
    ", (*test).size());
        //可以获取长度,2
        for (auto itt : (*test))
        {
            printf("test:%d
    ", itt);
        }
        //可遍历
    
        return 0;
    }
  • 相关阅读:
    delphi快捷键
    Delphi代码规范
    Hibernate通用Dao
    SpringData初探
    Windows下shell神器
    正则语法总结
    nodejs的npm命令无反应的解决方案
    JavaScript中,返回上一个页面时,如何保证上一个页面的不刷新?
    js上传图片
    正则匹配结果取反(正则中的前瞻,负向前瞻与后顾)
  • 原文地址:https://www.cnblogs.com/0-lingdu/p/12327136.html
Copyright © 2020-2023  润新知